From 180fb2dbe898bfe7e46ffdc6fd8c9072b4e78023 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Mon, 8 Sep 2025 17:43:46 -0700 Subject: [PATCH 1/3] Only set images field if multimodal is enabled --- app/backend/prepdocslib/searchmanager.py | 77 +++++++++++++----- data/en_An Occurrence at Owl Creek Bridge.pdf | Bin 127176 -> 0 bytes 2 files changed, 56 insertions(+), 21 deletions(-) delete mode 100644 data/en_An Occurrence at Owl Creek Bridge.pdf diff --git a/app/backend/prepdocslib/searchmanager.py b/app/backend/prepdocslib/searchmanager.py index 54cd1818ca..f9646e2eef 100644 --- a/app/backend/prepdocslib/searchmanager.py +++ b/app/backend/prepdocslib/searchmanager.py @@ -83,7 +83,6 @@ async def create_index(self): logger.info("Checking whether search index %s exists...", self.search_info.index_name) async with self.search_info.create_search_index_client() as search_index_client: - embedding_field = None images_field = None text_vector_search_profile = None @@ -231,7 +230,12 @@ async def create_index(self): type="Edm.String", analyzer_name=self.search_analyzer_name, ), - SimpleField(name="category", type="Edm.String", filterable=True, facetable=True), + SimpleField( + name="category", + type="Edm.String", + filterable=True, + facetable=True, + ), SimpleField( name="sourcepage", type="Edm.String", @@ -276,7 +280,10 @@ async def create_index(self): vector_algorithms: list[VectorSearchAlgorithmConfiguration] = [] vector_compressions: list[VectorSearchCompression] = [] if embedding_field: - logger.info("Including %s field for text vectors in new index", embedding_field.name) + logger.info( + "Including %s field for text vectors in new index", + embedding_field.name, + ) fields.append(embedding_field) if text_vectorizer is not None: vectorizers.append(text_vectorizer) @@ -291,7 +298,10 @@ async def create_index(self): vector_compressions.append(text_vector_compression) if images_field: - logger.info("Including %s field for image descriptions and vectors in new index", images_field.name) + logger.info( + "Including %s field for image descriptions and vectors in new index", + images_field.name, + ) fields.append(images_field) if image_vector_search_profile is None or image_vector_algorithm is None: raise ValueError("Image search profile and algorithm must be set") @@ -328,7 +338,10 @@ async def create_index(self): logger.info("Search index %s already exists", self.search_info.index_name) existing_index = await search_index_client.get_index(self.search_info.index_name) if not any(field.name == "storageUrl" for field in existing_index.fields): - logger.info("Adding storageUrl field to index %s", self.search_info.index_name) + logger.info( + "Adding storageUrl field to index %s", + self.search_info.index_name, + ) existing_index.fields.append( SimpleField( name="storageUrl", @@ -393,7 +406,10 @@ async def create_index(self): if existing_index.semantic_search: if not existing_index.semantic_search.default_configuration_name: - logger.info("Adding default semantic configuration to index %s", self.search_info.index_name) + logger.info( + "Adding default semantic configuration to index %s", + self.search_info.index_name, + ) existing_index.semantic_search.default_configuration_name = "default" if existing_index.semantic_search.configurations: @@ -403,7 +419,10 @@ async def create_index(self): and existing_semantic_config.prioritized_fields.title_field and not existing_semantic_config.prioritized_fields.title_field.field_name == "sourcepage" ): - logger.info("Updating semantic configuration for index %s", self.search_info.index_name) + logger.info( + "Updating semantic configuration for index %s", + self.search_info.index_name, + ) existing_semantic_config.prioritized_fields.title_field = SemanticField( field_name="sourcepage" ) @@ -413,7 +432,10 @@ async def create_index(self): or len(existing_index.vector_search.vectorizers) == 0 ): if self.embeddings is not None and isinstance(self.embeddings, AzureOpenAIEmbeddingService): - logger.info("Adding vectorizer to search index %s", self.search_info.index_name) + logger.info( + "Adding vectorizer to search index %s", + self.search_info.index_name, + ) existing_index.vector_search.vectorizers = [ AzureOpenAIVectorizer( vectorizer_name=f"{self.search_info.index_name}-vectorizer", @@ -445,7 +467,8 @@ async def create_agent(self): name=self.search_info.agent_name, target_indexes=[ KnowledgeAgentTargetIndex( - index_name=self.search_info.index_name, default_include_reference_source_data=True + index_name=self.search_info.index_name, + default_include_reference_source_data=True, ) ], models=[ @@ -471,15 +494,9 @@ async def update_content(self, sections: list[Section], url: Optional[str] = Non async with self.search_info.create_search_client() as search_client: for batch_index, batch in enumerate(section_batches): - documents = [ - { - "id": f"{section.content.filename_to_id()}-page-{section_index + batch_index * MAX_BATCH_SIZE}", - "content": section.chunk.text, - "category": section.category, - "sourcepage": BlobManager.sourcepage_from_file_page( - filename=section.content.filename(), page=section.chunk.page_num - ), - "sourcefile": section.content.filename(), + image_fields = {} + if self.search_images: + image_fields = { "images": [ { "url": image.url, @@ -487,8 +504,21 @@ async def update_content(self, sections: list[Section], url: Optional[str] = Non "boundingbox": image.bbox, "embedding": image.embedding, } + for section in batch for image in section.chunk.images - ], + ] + } + documents = [ + { + "id": f"{section.content.filename_to_id()}-page-{section_index + batch_index * MAX_BATCH_SIZE}", + "content": section.chunk.text, + "category": section.category, + "sourcepage": BlobManager.sourcepage_from_file_page( + filename=section.content.filename(), + page=section.chunk.page_num, + ), + "sourcefile": section.content.filename(), + **image_fields, **section.content.acls, } for section_index, section in enumerate(batch) @@ -514,7 +544,9 @@ async def update_content(self, sections: list[Section], url: Optional[str] = Non async def remove_content(self, path: Optional[str] = None, only_oid: Optional[str] = None): logger.info( - "Removing sections from '{%s or ''}' from search index '%s'", path, self.search_info.index_name + "Removing sections from '{%s or ''}' from search index '%s'", + path, + self.search_info.index_name, ) async with self.search_info.create_search_client() as search_client: while True: @@ -526,7 +558,10 @@ async def remove_content(self, path: Optional[str] = None, only_oid: Optional[st filter = f"sourcefile eq '{path_for_filter}'" max_results = 1000 result = await search_client.search( - search_text="", filter=filter, top=max_results, include_total_count=True + search_text="", + filter=filter, + top=max_results, + include_total_count=True, ) result_count = await result.get_count() if result_count == 0: diff --git a/data/en_An Occurrence at Owl Creek Bridge.pdf b/data/en_An Occurrence at Owl Creek Bridge.pdf deleted file mode 100644 index 1b19d2d2494c280d4e5b14ae505dc9b58037fd2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127176 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⁣4{5;d#UJhUX2> z8=f~jZ+PDDyy1Dn^M>aQ&l{dMJl~1t$9<#WdBgLD=MB#ro;N&ic)kl1&-TIdhUX2> z8=f~jziK`1_tS>wS6#xfA3Se(-tc^{je+kwpHuH+V!zXmhUX2>8=f~jZ+PDDyy5vS z;yBw3&l{dMJa2g3@Vw!9!}Esc4bOMc#n}&d-tfHPdBgLD=MB#ro;N⁣4{*sv$bA zXL!EUs{Oi;)n1Yb+s=Lr zJRf*I@O^ zUd#R1x3FWseQDflxgYzK-|NpG`&8a);df!==RLRH9d{QzUbQm!ZQt+TCI4=Fefjd+ z?_Xb@pZ5O+{DSjkKJ2mF<92WOPTzifYxrL$dRYAc From 8bc3fec0e792a1743d87994882874652c4772b6a Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Mon, 8 Sep 2025 17:52:51 -0700 Subject: [PATCH 2/3] Fix ingestion for non-multimodal case --- app/backend/prepdocslib/searchmanager.py | 88 ++++++++---------------- tests/test_searchmanager.py | 29 ++++++++ 2 files changed, 58 insertions(+), 59 deletions(-) diff --git a/app/backend/prepdocslib/searchmanager.py b/app/backend/prepdocslib/searchmanager.py index f9646e2eef..0fdf57580f 100644 --- a/app/backend/prepdocslib/searchmanager.py +++ b/app/backend/prepdocslib/searchmanager.py @@ -83,6 +83,7 @@ async def create_index(self): logger.info("Checking whether search index %s exists...", self.search_info.index_name) async with self.search_info.create_search_index_client() as search_index_client: + embedding_field = None images_field = None text_vector_search_profile = None @@ -230,12 +231,7 @@ async def create_index(self): type="Edm.String", analyzer_name=self.search_analyzer_name, ), - SimpleField( - name="category", - type="Edm.String", - filterable=True, - facetable=True, - ), + SimpleField(name="category", type="Edm.String", filterable=True, facetable=True), SimpleField( name="sourcepage", type="Edm.String", @@ -280,10 +276,7 @@ async def create_index(self): vector_algorithms: list[VectorSearchAlgorithmConfiguration] = [] vector_compressions: list[VectorSearchCompression] = [] if embedding_field: - logger.info( - "Including %s field for text vectors in new index", - embedding_field.name, - ) + logger.info("Including %s field for text vectors in new index", embedding_field.name) fields.append(embedding_field) if text_vectorizer is not None: vectorizers.append(text_vectorizer) @@ -298,10 +291,7 @@ async def create_index(self): vector_compressions.append(text_vector_compression) if images_field: - logger.info( - "Including %s field for image descriptions and vectors in new index", - images_field.name, - ) + logger.info("Including %s field for image descriptions and vectors in new index", images_field.name) fields.append(images_field) if image_vector_search_profile is None or image_vector_algorithm is None: raise ValueError("Image search profile and algorithm must be set") @@ -338,10 +328,7 @@ async def create_index(self): logger.info("Search index %s already exists", self.search_info.index_name) existing_index = await search_index_client.get_index(self.search_info.index_name) if not any(field.name == "storageUrl" for field in existing_index.fields): - logger.info( - "Adding storageUrl field to index %s", - self.search_info.index_name, - ) + logger.info("Adding storageUrl field to index %s", self.search_info.index_name) existing_index.fields.append( SimpleField( name="storageUrl", @@ -406,10 +393,7 @@ async def create_index(self): if existing_index.semantic_search: if not existing_index.semantic_search.default_configuration_name: - logger.info( - "Adding default semantic configuration to index %s", - self.search_info.index_name, - ) + logger.info("Adding default semantic configuration to index %s", self.search_info.index_name) existing_index.semantic_search.default_configuration_name = "default" if existing_index.semantic_search.configurations: @@ -419,10 +403,7 @@ async def create_index(self): and existing_semantic_config.prioritized_fields.title_field and not existing_semantic_config.prioritized_fields.title_field.field_name == "sourcepage" ): - logger.info( - "Updating semantic configuration for index %s", - self.search_info.index_name, - ) + logger.info("Updating semantic configuration for index %s", self.search_info.index_name) existing_semantic_config.prioritized_fields.title_field = SemanticField( field_name="sourcepage" ) @@ -432,10 +413,7 @@ async def create_index(self): or len(existing_index.vector_search.vectorizers) == 0 ): if self.embeddings is not None and isinstance(self.embeddings, AzureOpenAIEmbeddingService): - logger.info( - "Adding vectorizer to search index %s", - self.search_info.index_name, - ) + logger.info("Adding vectorizer to search index %s", self.search_info.index_name) existing_index.vector_search.vectorizers = [ AzureOpenAIVectorizer( vectorizer_name=f"{self.search_info.index_name}-vectorizer", @@ -467,8 +445,7 @@ async def create_agent(self): name=self.search_info.agent_name, target_indexes=[ KnowledgeAgentTargetIndex( - index_name=self.search_info.index_name, - default_include_reference_source_data=True, + index_name=self.search_info.index_name, default_include_reference_source_data=True ) ], models=[ @@ -494,35 +471,33 @@ async def update_content(self, sections: list[Section], url: Optional[str] = Non async with self.search_info.create_search_client() as search_client: for batch_index, batch in enumerate(section_batches): - image_fields = {} - if self.search_images: - image_fields = { - "images": [ - { - "url": image.url, - "description": image.description, - "boundingbox": image.bbox, - "embedding": image.embedding, - } - for section in batch - for image in section.chunk.images - ] - } - documents = [ - { + documents = [] + for section_index, section in enumerate(batch): + image_fields = {} + if self.search_images: + image_fields = { + "images": [ + { + "url": image.url, + "description": image.description, + "boundingbox": image.bbox, + "embedding": image.embedding, + } + for image in section.chunk.images + ] + } + document = { "id": f"{section.content.filename_to_id()}-page-{section_index + batch_index * MAX_BATCH_SIZE}", "content": section.chunk.text, "category": section.category, "sourcepage": BlobManager.sourcepage_from_file_page( - filename=section.content.filename(), - page=section.chunk.page_num, + filename=section.content.filename(), page=section.chunk.page_num ), "sourcefile": section.content.filename(), **image_fields, **section.content.acls, } - for section_index, section in enumerate(batch) - ] + documents.append(document) if url: for document in documents: document["storageUrl"] = url @@ -544,9 +519,7 @@ async def update_content(self, sections: list[Section], url: Optional[str] = Non async def remove_content(self, path: Optional[str] = None, only_oid: Optional[str] = None): logger.info( - "Removing sections from '{%s or ''}' from search index '%s'", - path, - self.search_info.index_name, + "Removing sections from '{%s or ''}' from search index '%s'", path, self.search_info.index_name ) async with self.search_info.create_search_client() as search_client: while True: @@ -558,10 +531,7 @@ async def remove_content(self, path: Optional[str] = None, only_oid: Optional[st filter = f"sourcefile eq '{path_for_filter}'" max_results = 1000 result = await search_client.search( - search_text="", - filter=filter, - top=max_results, - include_total_count=True, + search_text="", filter=filter, top=max_results, include_total_count=True ) result_count = await result.get_count() if result_count == 0: diff --git a/tests/test_searchmanager.py b/tests/test_searchmanager.py index 153c80ba75..6b60e68e16 100644 --- a/tests/test_searchmanager.py +++ b/tests/test_searchmanager.py @@ -316,6 +316,35 @@ async def mock_upload_documents(self, documents): ] +@pytest.mark.asyncio +async def test_update_content_no_images_when_disabled(monkeypatch, search_info): + """Ensure no 'images' field is added when search_images is False (baseline case without any images).""" + + documents_uploaded: list[dict] = [] + + async def mock_upload_documents(self, documents): + documents_uploaded.extend(documents) + + monkeypatch.setattr(SearchClient, "upload_documents", mock_upload_documents) + + manager = SearchManager(search_info, search_images=False) + + test_io = io.BytesIO(b"test file") + test_io.name = "test/foo.pdf" + file = File(test_io) + + section = Section( + chunk=Chunk(page_num=0, text="chunk text"), + content=file, + category="test", + ) + + await manager.update_content([section]) + + assert len(documents_uploaded) == 1, "Exactly one document should be uploaded" + assert "images" not in documents_uploaded[0], "'images' field should not be present when search_images is False" + + class AsyncSearchResultsIterator: def __init__(self, results): self.results = results From c7cca61dfa5bebd18eea668b21b9c5d1a754805c Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Mon, 8 Sep 2025 18:06:40 -0700 Subject: [PATCH 3/3] Update tests and snapshots --- .../text_splitter_sections.txt | 52 ------------------- tests/test_prepdocslib_filestrategy.py | 3 -- tests/test_searchmanager.py | 49 +++++++++++++++++ 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/tests/snapshots/test_prepdocslib_textsplitter/test_sentencetextsplitter_list_parse_and_split/text_splitter_sections.txt b/tests/snapshots/test_prepdocslib_textsplitter/test_sentencetextsplitter_list_parse_and_split/text_splitter_sections.txt index 711f0bd16a..e5e23f2927 100644 --- a/tests/snapshots/test_prepdocslib_textsplitter/test_sentencetextsplitter_list_parse_and_split/text_splitter_sections.txt +++ b/tests/snapshots/test_prepdocslib_textsplitter/test_sentencetextsplitter_list_parse_and_split/text_splitter_sections.txt @@ -669,58 +669,6 @@ " \n \nIf you have any questions or concerns about Contoso Electronics\u2019 data security program, \nplease contact our data security team. We are committed to keeping your data secure and \nwe appreciate your continued trust. Thank you for being a valued customer. \nJob Roles \n \n1. Chief Executive Officer \n2. Chief Operating Officer \n3. Chief Financial Officer \n4. Chief Technology Officer \n5. Vice President of Sales \n6. Vice President of Marketing \n7. Vice President of Operations \n8. Vice President of Human Resources \n9. Vice President of Research and Development \n10. Vice President of Product Management \n11. Director of Sales \n12. Director of Marketing \n13. Director of Operations \n14. Director of Human Resources ", "15. Director of Research and Development \n16. Director of Product Management \n17. Senior Manager of Sales \n18. Senior Manager of Marketing \n19. Senior Manager of Operations \n20. Senior Manager of Human Resources \n21. Senior Manager of Research and Development \n22. Senior Manager of Product Management \n23. Manager of Sales \n24. Manager of Marketing \n25. Manager of Operations \n26. Manager of Human Resources \n27. Manager of Research and Development \n28. Manager of Product Management \n29. Sales Representative \n30. Customer Service Representative " ], - "en_An Occurrence at Owl Creek Bridge.pdf": [ - "The Project Gutenberg eBook of An Occurrence at Owl Creek Bridge \n \nThis ebook is for the use of anyone anywhere in the United States and \nmost other parts of the world at no cost and with almost no restrictions \nwhatsoever. You may copy it, give it away or re-use it under the terms \nof the Project Gutenberg License included with this ebook or online \nat www.gutenberg.org. If you are not located in the United States, \nyou will have to check the laws of the country where you are located \nbefore using this eBook. \n \nTitle: An Occurrence at Owl Creek Bridge \n \n \nAuthor: Ambrose Bierce \n \nRelease date: December 1, 1995 [eBook #375] \n ", - " \n \nTitle: An Occurrence at Owl Creek Bridge \n \n \nAuthor: Ambrose Bierce \n \nRelease date: December 1, 1995 [eBook #375] \n Most recently updated: April 25, 2022 \n \nLanguage: English \n \n \n \n*** START OF THE PROJECT GUTENBERG EBOOK AN OCCURRENCE AT OWL CREEK BRIDGE \n*** \n \n \n \n \nAn Occurrence at Owl Creek Bridge \n \nby Ambrose Bierce \n \nTHE MILLENNIUM FULCRUM EDITION, 1988 \n \n \n \n \nI \n \n \nA man stood upon a railroad bridge in northern Alabama, looking down \ninto the swift water twenty feet below. The man\u2019s hands were behind his \nback, the wrists bound with a cord. A rope closely encircled his neck. \nIt was attached to a stout cross-timber above his head and the slack \nfell to the level of his knees. Some loose boards laid upon the ties \nsupporting the rails of the railway supplied a footing for him and his \nexecutioners\u2014two private soldiers of the Federal army, directed by a \nsergeant who in civil life may have been a deputy sheriff. At a short \nremove upon the same temporary platform was an officer in the uniform \nof his rank, armed.", - " At a short \nremove upon the same temporary platform was an officer in the uniform \nof his rank, armed. He was a captain. A sentinel at each end of the \nbridge stood with his rifle in the position known as \u201csupport,\u201d that is \nto say, vertical in front of the left shoulder, the hammer resting on \nthe forearm thrown straight across the chest\u2014a formal and unnatural \nposition, enforcing an erect carriage of the body. It did not appear to \nbe the duty of these two men to know what was occurring at the center \nof the bridge; they merely blockaded the two ends of the foot planking \nthat traversed it. \n \nBeyond one of the sentinels nobody was in sight; the railroad ran \nstraight away into a forest for a hundred yards, then, curving, was \nlost to view. Doubtless there was an outpost farther along.", - " The other bank of the stream was open ground\u2014a gentle slope topped with a \nstockade of vertical tree trunks, loopholed for rifles, with a single \nembrasure through which protruded the muzzle of a brass cannon \ncommanding the bridge. Midway up the slope between the bridge and fort \nwere the spectators\u2014a single company of infantry in line, at \u201cparade \nrest,\u201d the butts of their rifles on the ground, the barrels inclining \nslightly backward against the right shoulder, the hands crossed upon \nthe stock. A lieutenant stood at the right of the line, the point of \nhis sword upon the ground, his left hand resting upon his right. \nExcepting the group of four at the center of the bridge, not a man \nmoved. The company faced the bridge, staring stonily, motionless. The \nsentinels, facing the banks of the stream, might have been statues to \nadorn the bridge. The captain stood with folded arms, silent, observing \nthe work of his subordinates, but making no sign. Death is a dignitary \nwho when he comes announced is to be received with formal \nmanifestations of respect, even by those ", - " Death is a dignitary \nwho when he comes announced is to be received with formal \nmanifestations of respect, even by those most familiar with him. In the \ncode of military etiquette silence and fixity are forms of deference. \n \nThe man who was engaged in being hanged was apparently about \nthirty-five years of age. He was a civilian, if one might judge from \nhis habit, which was that of a planter. His features were good\u2014a \nstraight nose, firm mouth, broad forehead, from which his long, dark \nhair was combed straight back, falling behind his ears to the collar of \nhis well fitting frock coat. He wore a moustache and pointed beard, but \nno whiskers; his eyes were large and dark gray, and had a kindly \nexpression which one would hardly have expected in one whose neck was \nin the hemp. Evidently this was no vulgar assassin. The liberal \nmilitary code makes provision for hanging many kinds of persons, and \ngentlemen are not excluded. \n \nThe preparations being complete, the two private soldiers stepped aside \nand each drew away the plank upon which he had ", - " \n \nThe preparations being complete, the two private soldiers stepped aside \nand each drew away the plank upon which he had been standing. The \nsergeant turned to the captain, saluted and placed himself immediately \nbehind that officer, who in turn moved apart one pace. These movements \nleft the condemned man and the sergeant standing on the two ends of the \nsame plank, which spanned three of the cross-ties of the bridge. The \nend upon which the civilian stood almost, but not quite, reached a \nfourth. This plank had been held in place by the weight of the captain; \nit was now held by that of the sergeant. At a signal from the former \nthe latter would step aside, the plank would tilt and the condemned man \ngo down between two ties. The arrangement commended itself to his \njudgement as simple and effective. His face had not been covered nor \nhis eyes bandaged. He looked a moment at his \u201cunsteadfast footing,\u201d \nthen let his gaze wander to the swirling water of the stream racing \nmadly ", - " He looked a moment at his \u201cunsteadfast footing,\u201d \nthen let his gaze wander to the swirling water of the stream racing \nmadly beneath his feet. A piece of dancing driftwood caught his \nattention and his eyes followed it down the current. How slowly it \nappeared to move! What a sluggish stream! \n \nHe closed his eyes in order to fix his last thoughts upon his wife and \nchildren. The water, touched to gold by the early sun, the brooding \nmists under the banks at some distance down the stream, the fort, the \nsoldiers, the piece of drift\u2014all had distracted him. And now he became \nconscious of a new disturbance. Striking through the thought of his \ndear ones was sound which he could neither ignore nor understand, a \nsharp, distinct, metallic percussion like the stroke of a blacksmith\u2019s \nhammer upon the anvil; it had the same ringing quality. He wondered \nwhat it was, and whether immeasurably distant or near by\u2014 it seemed \nboth. Its recurrence was regular, but as slow as the tolling of a death \nknell. He awaited each new stroke with impatience and\u2014", - " Its recurrence was regular, but as slow as the tolling of a death \nknell. He awaited each new stroke with impatience and\u2014he knew not \nwhy\u2014apprehension. The intervals of silence grew progressively longer; \nthe delays became maddening. With their greater infrequency the sounds increased in strength and sharpness. They hurt his ear like the thrust \nof a knife; he feared he would shriek. What he heard was the ticking of \nhis watch. \n \nHe unclosed his eyes and saw again the water below him. \u201cIf I could \nfree my hands,\u201d he thought, \u201cI might throw off the noose and spring \ninto the stream. By diving I could evade the bullets and, swimming \nvigorously, reach the bank, take to the woods and get away home. My \nhome, thank God, is as yet outside their lines; my wife and little ones \nare still beyond the invader\u2019s farthest advance.\u201d \n \nAs these thoughts, which have here to be set down in words, were \nflashed into the doomed man\u2019s brain rather than evolved from it the \ncaptain nodded to the sergeant. The sergeant stepped aside. \n \n \n \n \nII \n \n \nPeyton Farquhar was a well to do planter, of an old and highly \nrespected Alabama family.", - " Being a slave owner and like other slave \nowners a politician, he was naturally an original secessionist and \nardently devoted to the Southern cause. Circumstances of an imperious \nnature, which it is unnecessary to relate here, had prevented him from \ntaking service with that gallant army which had fought the disastrous \ncampaigns ending with the fall of Corinth, and he chafed under the \ninglorious restraint, longing for the release of his energies, the \nlarger life of the soldier, the opportunity for distinction. That \nopportunity, he felt, would come, as it comes to all in wartime. \nMeanwhile he did what he could. No service was too humble for him to \nperform in the aid of the South, no adventure too perilous for him to \nundertake if consistent with the character of a civilian who was at \nheart a soldier, and who in good faith and without too much \nqualification assented to at least a part of the frankly villainous \ndictum that all is fair in love and war. \n \nOne evening while Farquhar and his wife were sitting on a rustic bench \nnear the entrance to his grounds, a gray-clad ", - " \n \nOne evening while Farquhar and his wife were sitting on a rustic bench \nnear the entrance to his grounds, a gray-clad soldier rode up to the \ngate and asked for a drink of water. Mrs. Farquhar was only too happy \nto serve him with her own white hands. While she was fetching the water \nher husband approached the dusty horseman and inquired eagerly for news \nfrom the front. \n \n\u201cThe Yanks are repairing the railroads,\u201d said the man, \u201cand are getting \nready for another advance. They have reached the Owl Creek bridge, put \nit in order and built a stockade on the north bank. The commandant has \nissued an order, which is posted everywhere, declaring that any \ncivilian caught interfering with the railroad, its bridges, tunnels, or \ntrains will be summarily hanged. I saw the order.\u201d \n \n\u201cHow far is it to the Owl Creek bridge?\u201d Farquhar asked. \n \n\u201cAbout thirty miles.\u201d \n \n\u201cIs there no force on this side of the creek?\u201d \n \n\u201cOnly a picket post half a mile out, on the railroad, and a single \nsentinel at this end of the bridge.", - "\u201d \n \n\u201cOnly a picket post half a mile out, on the railroad, and a single \nsentinel at this end of the bridge.\u201d \n ", - "\u201cSuppose a man\u2014a civilian and student of hanging\u2014should elude the \npicket post and perhaps get the better of the sentinel,\u201d said Farquhar, \nsmiling, \u201cwhat could he accomplish?\u201d \n \nThe soldier reflected. \u201cI was there a month ago,\u201d he replied. \u201cI \nobserved that the flood of last winter had lodged a great quantity of \ndriftwood against the wooden pier at this end of the bridge. It is now \ndry and would burn like tinder.\u201d \n \nThe lady had now brought the water, which the soldier drank. He thanked \nher ceremoniously, bowed to her husband and rode away. An hour later, \nafter nightfall, he repassed the plantation, going northward in the \ndirection from which he had come. He was a Federal scout. \n \n \n \n \nIII \n \n \nAs Peyton Farquhar fell straight downward through the bridge he lost \nconsciousness and was as one already dead. From this state he was \nawakened\u2014ages later, it seemed to him\u2014by the pain of a sharp pressure \nupon his throat, followed by a sense of suffocation. Keen, poignant \nagonies seemed to shoot from his neck downward through every fiber of \nhis body and limbs.", - " Keen, poignant \nagonies seemed to shoot from his neck downward through every fiber of \nhis body and limbs. These pains appeared to flash along well defined \nlines of ramification and to beat with an inconceivably rapid \nperiodicity. They seemed like streams of pulsating fire heating him to \nan intolerable temperature. As to his head, he was conscious of nothing \nbut a feeling of fullness\u2014of congestion. These sensations were \nunaccompanied by thought. The intellectual part of his nature was \nalready effaced; he had power only to feel, and feeling was torment. He \nwas conscious of motion. Encompassed in a luminous cloud, of which he \nwas now merely the fiery heart, without material substance, he swung \nthrough unthinkable arcs of oscillation, like a vast pendulum. Then all \nat once, with terrible suddenness, the light about him shot upward with \nthe noise of a loud splash; a frightful roaring was in his ears, and \nall was cold and dark. The power of thought was restored; he knew that \nthe rope had broken and he had fallen into the stream.", - " The power of thought was restored; he knew that \nthe rope had broken and he had fallen into the stream. There was no \nadditional strangulation; the noose about his neck was already \nsuffocating him and kept the water from his lungs. To die of hanging at \nthe bottom of a river!\u2014the idea seemed to him ludicrous. He opened his \neyes in the darkness and saw above him a gleam of light, but how \ndistant, how inaccessible! He was still sinking, for the light became \nfainter and fainter until it was a mere glimmer. Then it began to grow \nand brighten, and he knew that he was rising toward the surface\u2014knew it \nwith reluctance, for he was now very comfortable. \u201cTo be hanged and \ndrowned,\u201d he thought, \u201cthat is not so bad; but I do not wish to be \nshot. No; I will not be shot; that is not fair.\u201d \n \nHe was not conscious of an effort, but a sharp pain in his wrist \napprised him that he was trying to free his hands. He gave the struggle \nhis attention, as an idler might observe the feat of a juggler, without \ninterest in the outcome.", - " He gave the struggle \nhis attention, as an idler might observe the feat of a juggler, without \ninterest in the outcome. What splendid effort!\u2014what magnificent, what \nsuperhuman strength! Ah, that was a fine endeavor! Bravo! The cord fell \naway; his arms parted and floated upward, the hands dimly seen on each \nside in the growing light. He watched them with a new interest as first \none and then the other pounced upon the noose at his neck. They tore it \naway and thrust it fiercely aside, its undulations resembling those of \na water snake. \u201cPut it back, put it back!", - "\u201d He thought he shouted these \nwords to his hands, for the undoing of the noose had been succeeded by the direst pang that he had yet experienced. His neck ached horribly; \nhis brain was on fire, his heart, which had been fluttering faintly, \ngave a great leap, trying to force itself out at his mouth. His whole \nbody was racked and wrenched with an insupportable anguish! But his \ndisobedient hands gave no heed to the command. They beat the water \nvigorously with quick, downward strokes, forcing him to the surface. He \nfelt his head emerge; his eyes were blinded by the sunlight; his chest \nexpanded convulsively, and with a supreme and crowning agony his lungs \nengulfed a great draught of air, which instantly he expelled in a \nshriek! \n \nHe was now in full possession of his physical senses. They were, \nindeed, preternaturally keen and alert. Something in the awful \ndisturbance of his organic system had so exalted and refined them that \nthey made record of things never before perceived. He felt the ripples \nupon his face and heard their separate sounds as they struck. He looked \nat the forest on the bank of the stream, saw the individual trees, the \nleaves and the veining of each leaf", - " He looked \nat the forest on the bank of the stream, saw the individual trees, the \nleaves and the veining of each leaf\u2014he saw the very insects upon them: \nthe locusts, the brilliant bodied flies, the gray spiders stretching \ntheir webs from twig to twig. He noted the prismatic colors in all the \ndewdrops upon a million blades of grass. The humming of the gnats that \ndanced above the eddies of the stream, the beating of the dragon flies\u2019 \nwings, the strokes of the water spiders\u2019 legs, like oars which had \nlifted their boat\u2014all these made audible music. A fish slid along \nbeneath his eyes and he heard the rush of its body parting the water. \n \nHe had come to the surface facing down the stream; in a moment the \nvisible world seemed to wheel slowly round, himself the pivotal point, \nand he saw the bridge, the fort, the soldiers upon the bridge, the \ncaptain, the sergeant, the two privates, his executioners. They were in \nsilhouette against the blue sky. They shouted and gesticulated, \npointing at him. The captain had drawn his pistol, but did not fire; \nthe others were unarmed.", - " They shouted and gesticulated, \npointing at him. The captain had drawn his pistol, but did not fire; \nthe others were unarmed. Their movements were grotesque and horrible, \ntheir forms gigantic. \n \nSuddenly he heard a sharp report and something struck the water smartly \nwithin a few inches of his head, spattering his face with spray. He \nheard a second report, and saw one of the sentinels with his rifle at \nhis shoulder, a light cloud of blue smoke rising from the muzzle. The \nman in the water saw the eye of the man on the bridge gazing into his \nown through the sights of the rifle. He observed that it was a gray eye \nand remembered having read that gray eyes were keenest, and that all \nfamous marksmen had them. Nevertheless, this one had missed. \n \nA counter-swirl had caught Farquhar and turned him half round; he was \nagain looking at the forest on the bank opposite the fort. The sound of \na clear, high voice in a monotonous singsong now rang out behind him \nand came across the water with a distinctness ", - " The sound of \na clear, high voice in a monotonous singsong now rang out behind him \nand came across the water with a distinctness that pierced and subdued \nall other sounds, even the beating of the ripples in his ears. Although \nno soldier, he had frequented camps enough to know the dread \nsignificance of that deliberate, drawling, aspirated chant; the \nlieutenant on shore was taking a part in the morning\u2019s work. How coldly \nand pitilessly\u2014with what an even, calm intonation, presaging, and \nenforcing tranquility in the men\u2014with what accurately measured interval \nfell those cruel words: \n \n\u201cCompany!\u2026 Attention!\u2026 Shoulder arms!\u2026 Ready!\u2026 Aim!\u2026 Fire!\u201d \n \nFarquhar dived\u2014dived as deeply as he could.", - " The water roared in his \nears like the voice of Niagara, yet he heard the dull thunder of the \nvolley and, rising again toward the surface, met shining bits of metal, singularly flattened, oscillating slowly downward. Some of them touched \nhim on the face and hands, then fell away, continuing their descent. \nOne lodged between his collar and neck; it was uncomfortably warm and \nhe snatched it out. \n \nAs he rose to the surface, gasping for breath, he saw that he had been \na long time under water; he was perceptibly farther downstream\u2014nearer \nto safety. The soldiers had almost finished reloading; the metal \nramrods flashed all at once in the sunshine as they were drawn from the \nbarrels, turned in the air, and thrust into their sockets. The two \nsentinels fired again, independently and ineffectually. \n \nThe hunted man saw all this over his shoulder; he was now swimming \nvigorously with the current. His brain was as energetic as his arms and \nlegs; he thought with the rapidity of lightning: \n \n\u201cThe officer,\u201d he reasoned, \u201cwill not make that martinet\u2019s error a \nsecond time. It is as easy to dodge a volley as a single shot. He has \nprobably already given the command to fire at will. Go", - " He has \nprobably already given the command to fire at will. God help me, I \ncannot dodge them all!\u201d \n \nAn appalling splash within two yards of him was followed by a loud, \nrushing sound, DIMINUENDO, which seemed to travel back through the air \nto the fort and died in an explosion which stirred the very river to \nits deeps! A rising sheet of water curved over him, fell down upon him, \nblinded him, strangled him! The cannon had taken an hand in the game. \nAs he shook his head free from the commotion of the smitten water he \nheard the deflected shot humming through the air ahead, and in an \ninstant it was cracking and smashing the branches in the forest beyond. \n \n\u201cThey will not do that again,\u201d he thought; \u201cthe next time they will use \na charge of grape. I must keep my eye upon the gun; the smoke will \napprise me\u2014the report arrives too late; it lags behind the missile. \nThat is a good gun.\u201d \n \nSuddenly he felt himself whirled round and round\u2014spinning like a top. \nThe water, the banks, the forests, the now distant bridge, fort and \nmen, all were commingled and blurred.", - " \nThe water, the banks, the forests, the now distant bridge, fort and \nmen, all were commingled and blurred. Objects were represented by their \ncolors only; circular horizontal streaks of color\u2014that was all he saw. \nHe had been caught in a vortex and was being whirled on with a velocity \nof advance and gyration that made him giddy and sick. In few moments he \nwas flung upon the gravel at the foot of the left bank of the \nstream\u2014the southern bank\u2014and behind a projecting point which concealed \nhim from his enemies. The sudden arrest of his motion, the abrasion of \none of his hands on the gravel, restored him, and he wept with delight. \nHe dug his fingers into the sand, threw it over himself in handfuls and \naudibly blessed it. It looked like diamonds, rubies, emeralds; he could \nthink of nothing beautiful which it did not resemble. The trees upon \nthe bank were giant garden plants; he noted a definite order in their \narrangement, inhaled the fragrance of their blooms. A strange roseate \nlight shone through the spaces among their trunks and the wind made in \ntheir branches the music of AEolian ", - " A strange roseate \nlight shone through the spaces among their trunks and the wind made in \ntheir branches the music of AEolian harps. He had not wish to perfect \nhis escape\u2014he was content to remain in that enchanting spot until \nretaken. \n \nA whiz and a rattle of grapeshot among the branches high above his head \nroused him from his dream. The baffled cannoneer had fired him a random \nfarewell. He sprang to his feet, rushed up the sloping bank, and \nplunged into the forest. \n \nAll that day he traveled, laying his course by the rounding sun.", - " The forest seemed interminable; nowhere did he discover a break in it, not \neven a woodman\u2019s road. He had not known that he lived in so wild a \nregion. There was something uncanny in the revelation. \n \nBy nightfall he was fatigued, footsore, famished. The thought of his \nwife and children urged him on. At last he found a road which led him \nin what he knew to be the right direction. It was as wide and straight \nas a city street, yet it seemed untraveled. No fields bordered it, no \ndwelling anywhere. Not so much as the barking of a dog suggested human \nhabitation. The black bodies of the trees formed a straight wall on \nboth sides, terminating on the horizon in a point, like a diagram in a \nlesson in perspective. Overhead, as he looked up through this rift in \nthe wood, shone great golden stars looking unfamiliar and grouped in \nstrange constellations. He was sure they were arranged in some order \nwhich had a secret and malign significance. The wood on either side was \nfull of singular noises, among which\u2014once, twice, and again\u2014he \ndistinctly heard whispers in ", - " The wood on either side was \nfull of singular noises, among which\u2014once, twice, and again\u2014he \ndistinctly heard whispers in an unknown tongue. \n \nHis neck was in pain and lifting his hand to it found it horribly \nswollen. He knew that it had a circle of black where the rope had \nbruised it. His eyes felt congested; he could no longer close them. His \ntongue was swollen with thirst; he relieved its fever by thrusting it \nforward from between his teeth into the cold air. How softly the turf \nhad carpeted the untraveled avenue\u2014he could no longer feel the roadway \nbeneath his feet! \n \nDoubtless, despite his suffering, he had fallen asleep while walking, \nfor now he sees another scene\u2014perhaps he has merely recovered from a \ndelirium. He stands at the gate of his own home. All is as he left it, \nand all bright and beautiful in the morning sunshine. He must have \ntraveled the entire night. As he pushes open the gate and passes up the \nwide white walk, he sees a flutter of female garments; his wife, \nlooking fresh ", - " As he pushes open the gate and passes up the \nwide white walk, he sees a flutter of female garments; his wife, \nlooking fresh and cool and sweet, steps down from the veranda to meet \nhim. At the bottom of the steps she stands waiting, with a smile of \nineffable joy, an attitude of matchless grace and dignity. Ah, how \nbeautiful she is! He springs forwards with extended arms. As he is \nabout to clasp her he feels a stunning blow upon the back of the neck; \na blinding white light blazes all about him with a sound like the shock \nof a cannon\u2014then all is darkness and silence! \n \nPeyton Farquhar was dead; his body, with a broken neck, swung gently \nfrom side to side beneath the timbers of the Owl Creek bridge. \n \n \n \n \n \n \n *** END OF THE PROJECT GUTENBERG EBOOK AN OCCURRENCE AT OWL \nCREEK BRIDGE *** \n \n \n \n \nUpdated editions will replace the previous one\u2014the old editions will \nbe renamed. \n \nCreating the works from print editions not protected by U.S. copyright \nlaw means that no one owns a United States copyright in these works, \nso the Foundation (and you!", - " copyright \nlaw means that no one owns a United States copyright in these works, \nso the Foundation (and you!) can copy and distribute it in the United \nStates without permission and without paying copyright royalties. Special rules, set forth in the General Terms of Use part \nof this license, apply to copying and distributing Project \nGutenberg\u2122 electronic works to protect the PROJECT GUTENBERG\u2122 \nconcept and trademark. Project Gutenberg is a registered trademark, \nand may not be used if you charge for an eBook, except by following \nthe terms of the trademark license, including paying royalties for use \nof the Project Gutenberg trademark. If you do not charge anything for \ncopies of this eBook, complying with the trademark license is very \neasy. You may use this eBook for nearly any purpose such as creation \nof derivative works, reports, performances and research. Project \nGutenberg eBooks may be modified and printed and given away\u2014you may \ndo practically ANYTHING in the United States with eBooks not protected \nby U.S. copyright law. Redistribution is subject to the trademark \nlicense, especially commercial redistribution.", - " \n \n \nSTART: FULL LICENSE \n \nTHE FULL PROJECT GUTENBERG LICENSE \n \nPLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK \n \nTo protect the Project Gutenberg\u2122 mission of promoting the free \ndistribution of electronic works, by using or distributing this work \n(or any other work associated in any way with the phrase \u201cProject \nGutenberg\u201d), you agree to comply with all the terms of the Full \nProject Gutenberg\u2122 License available with this file or online at \nwww.gutenberg.org/license. \n \nSection 1. General Terms of Use and Redistributing Project Gutenberg\u2122 \nelectronic works \n \n1.A. By reading or using any part of this Project Gutenberg\u2122 \nelectronic work, you indicate that you have read, understand, agree to \nand accept all the terms of this license and intellectual property \n(trademark/copyright) agreement. If you do not agree to abide by all \nthe terms of this agreement, you must cease using and return or \ndestroy all copies of Project Gutenberg\u2122 electronic works in your \npossession. If you paid a fee for obtaining a copy of or access to a \nProject Gutenberg\u2122 electronic work and you do not agree to be bound ", - " If you paid a fee for obtaining a copy of or access to a \nProject Gutenberg\u2122 electronic work and you do not agree to be bound \nby the terms of this agreement, you may obtain a refund from the person \nor entity to whom you paid the fee as set forth in paragraph 1.E.8. \n \n1.B. \u201cProject Gutenberg\u201d is a registered trademark. It may only be \nused on or associated in any way with an electronic work by people who \nagree to be bound by the terms of this agreement. There are a few \nthings that you can do with most Project Gutenberg\u2122 electronic works \neven without complying with the full terms of this agreement. See \nparagraph 1.C below. There are a lot of things you can do with Project \nGutenberg\u2122 electronic works if you follow the terms of this \nagreement and help preserve free future access to Project Gutenberg\u2122 \nelectronic works. See paragraph 1.E below. \n \n1.C. The Project Gutenberg Literary Archive Foundation (\u201cthe \nFoundation\u201d or PGLAF), owns a compilation copyright in the collection ", - " The Project Gutenberg Literary Archive Foundation (\u201cthe \nFoundation\u201d or PGLAF), owns a compilation copyright in the collection \nof Project Gutenberg\u2122 electronic works. Nearly all the individual \nworks in the collection are in the public domain in the United \nStates.", - "ks based on the work as long as If an individual work is unprotected by copyright law in the \nUnited States and you are located in the United States, we do ", - "If an individual work is unprotected by copyright law in the \nUnited States and you are located in the United States, we do not \nclaim a right to prevent you from copying, distributing, performing, \ndisplaying or creating derivative wor all references to Project Gutenberg are removed. Of course, we hope \nthat you will support the Project Gutenberg\u2122 mission of promoting \nfree access to electronic works by freely sharing Project Gutenberg\u2122 \nworks in compliance with the terms of this agreement for keeping the \nProject Gutenberg\u2122 name associated with the work. You can easily \ncomply with the terms of this agreement by keeping this work in the \nsame format with its attached full Project Gutenberg\u2122 License when \nyou share it without charge with others. \n \n1.D. The copyright laws of the place where you are located also govern \nwhat you can do with this work. Copyright laws in most countries are \nin a constant state of change. If you are outside the United States, \ncheck the laws of your country in addition to the terms of this \nagreement before downloading, copying, displaying, performing, \ndistributing or creating derivative works based on this work or any \nother Project Gutenberg\u2122 work.", - " The Foundation makes no \nrepresentations concerning the copyright status of any work in any \ncountry other than the United States. \n \n1.E. Unless you have removed all references to Project Gutenberg: \n \n1.E.1. The following sentence, with active links to, or other \nimmediate access to, the full Project Gutenberg\u2122 License must appear \nprominently whenever any copy of a Project Gutenberg\u2122 work (any work \non which the phrase \u201cProject Gutenberg\u201d appears, or with which the \nphrase \u201cProject Gutenberg\u201d is associated) is accessed, displayed, \nperformed, viewed, copied or distributed: \n \n This eBook is for the use of anyone anywhere in the United States and \nmost \n other parts of the world at no cost and with almost no restrictions \n whatsoever. You may copy it, give it away or re-use it under the terms \n of the Project Gutenberg License included with this eBook or online \n at www.gutenberg.org. If you \n are not located in the United States, you will have to check the laws \n of the country where you are located ", - " If you \n are not located in the United States, you will have to check the laws \n of the country where you are located before using this eBook. \n \n1.E.2. If an individual Project Gutenberg\u2122 electronic work is \nderived from texts not protected by U.S. copyright law (does not \ncontain a notice indicating that it is posted with permission of the \ncopyright holder), the work can be copied and distributed to anyone in \nthe United States without paying any fees or charges. If you are \nredistributing or providing access to a work with the phrase \u201cProject \nGutenberg\u201d associated with or appearing on the work, you must comply \neither with the requirements of paragraphs 1.E.1 through 1.E.7 or \nobtain permission for the use of the work and the Project Gutenberg\u2122 \ntrademark as set forth in paragraphs 1.E.8 or 1.E.9. \n \n1.E.3. If an individual Project Gutenberg\u2122 electronic work is posted \nwith the permission of the copyright holder, your use and ", - " If an individual Project Gutenberg\u2122 electronic work is posted \nwith the permission of the copyright holder, your use and distribution \nmust comply with both paragraphs 1.E.1 through 1.E.7 and any \nadditional terms imposed by the copyright holder. Additional terms \nwill be linked to the Project Gutenberg\u2122 License for all works \nposted with the permission of the copyright holder found at the \nbeginning of this work. \n \n1.E.4. Do not unlink or detach or remove the full Project Gutenberg\u2122 \nLicense terms from this work, or any files containing a part of this \nwork or any other work associated with Project Gutenberg\u2122. \n \n1.E.5.", - " Do not copy, display, perform, distribute or redistribute this electronic work, or any part of this electronic work, without \nprominently displaying the sentence set forth in paragraph 1.E.1 with \nactive links or immediate access to the full terms of the Project \nGutenberg\u2122 License. \n \n1.E.6. You may convert to and distribute this work in any binary, \ncompressed, marked up, nonproprietary or proprietary form, including \nany word processing or hypertext form. However, if you provide access \nto or distribute copies of a Project Gutenberg\u2122 work in a format \nother than \u201cPlain Vanilla ASCII\u201d or other format used in the official \nversion posted on the official Project Gutenberg\u2122 website \n(www.gutenberg.org), you must, at no additional cost, fee or expense \nto the user, provide a copy, a means of exporting a copy, or a means \nof obtaining a copy upon request, of the work in its original \u201cPlain \nVanilla ASCII\u201d or other form. Any alternate format must include the \nfull Project Gutenberg\u2122 License as specified in paragraph 1.E.1. \n \n1.E.7. Do not charge a fee for access to, viewing, displaying, \nperforming, copying or distributing any Project Gutenberg\u2122 works ", - " Do not charge a fee for access to, viewing, displaying, \nperforming, copying or distributing any Project Gutenberg\u2122 works \nunless you comply with paragraph 1.E.8 or 1.E.9. \n \n1.E.8. You may charge a reasonable fee for copies of or providing \naccess to or distributing Project Gutenberg\u2122 electronic works \nprovided that: \n \n \u2022 You pay a royalty fee of 20% of the gross profits you derive from \n the use of Project Gutenberg\u2122 works calculated using the method \n you already use to calculate your applicable taxes. The fee is owed \n to the owner of the Project Gutenberg\u2122 trademark, but he has \n agreed to donate royalties under this paragraph to the Project \n Gutenberg Literary Archive Foundation. Royalty payments must be \npaid \n within 60 days following each date on which you prepare (or are \n legally required to prepare) your periodic tax returns. Royalty \n payments should be clearly marked as such and sent to the Project \n Gutenberg Literary Archive Foundation ", - " Royalty \n payments should be clearly marked as such and sent to the Project \n Gutenberg Literary Archive Foundation at the address specified in \n Section 4, \u201cInformation about donations to the Project Gutenberg \n Literary Archive Foundation.\u201d \n \n \u2022 You provide a full refund of any money paid by a user who notifies \n you in writing (or by e-mail) within 30 days of receipt that s/he \n does not agree to the terms of the full Project Gutenberg\u2122 \n License. You must require such a user to return or destroy all \n copies of the works possessed in a physical medium and discontinue \n all use of and all access to other copies of Project Gutenberg\u2122 \n works. \n \n \u2022 You provide, in accordance with paragraph 1.F.3, a full refund of \n any money paid for a work or a replacement copy, if a defect in the \n electronic work is discovered and reported to you within 90 days of \n receipt of the work. \n \n \u2022 You comply with all other terms of this agreement for free \n distribution of Project Gutenberg\u2122 works.", - " \n \n \u2022 You comply with all other terms of this agreement for free \n distribution of Project Gutenberg\u2122 works. \n \n \n1.E.9. If you wish to charge a fee or distribute a Project \nGutenberg\u2122 electronic work or group of works on different terms than \nare set forth in this agreement, you must obtain permission in writing \nfrom the Project Gutenberg Literary Archive Foundation, the manager of \nthe Project Gutenberg\u2122 trademark.", - " Contact the Foundation as set forth in Section 3 below. \n \n1.F. \n \n1.F.1. Project Gutenberg volunteers and employees expend considerable \neffort to identify, do copyright research on, transcribe and proofread \nworks not protected by U.S. copyright law in creating the Project \nGutenberg\u2122 collection. Despite these efforts, Project Gutenberg\u2122 \nelectronic works, and the medium on which they may be stored, may \ncontain \u201cDefects,\u201d such as, but not limited to, incomplete, inaccurate \nor corrupt data, transcription errors, a copyright or other \nintellectual property infringement, a defective or damaged disk or \nother medium, a computer virus, or computer codes that damage or \ncannot be read by your equipment. \n \n1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the \u201cRight \nof Replacement or Refund\u201d described in paragraph 1.F.3, the Project \nGutenberg Literary Archive Foundation, the owner of the Project \nGutenberg\u2122 trademark, and any other party ", - "3, the Project \nGutenberg Literary Archive Foundation, the owner of the Project \nGutenberg\u2122 trademark, and any other party distributing a Project \nGutenberg\u2122 electronic work under this agreement, disclaim all \nliability to you for damages, costs and expenses, including legal \nfees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT \nLIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE \nPROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE \nTRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE \nLIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR \nINCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH \nDAMAGE. \n \n1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a \ndefect in this electronic work within 90 days of receiving it, you can \nreceive a refund of the money (if any) you paid for it by sending a \nwritten explanation to the person you received the work from. If you \nreceived the work on a physical medium, you must return the medium \nwith your written explanation.", - " If you \nreceived the work on a physical medium, you must return the medium \nwith your written explanation. The person or entity that provided you \nwith the defective work may elect to provide a replacement copy in \nlieu of a refund. If you received the work electronically, the person \nor entity providing it to you may choose to give you a second \nopportunity to receive the work electronically in lieu of a refund. If \nthe second copy is also defective, you may demand a refund in writing \nwithout further opportunities to fix the problem. \n \n1.F.4. Except for the limited right of replacement or refund set forth \nin paragraph 1.F.3, this work is provided to you \u2018AS-IS\u2019, WITH NO \nOTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PURPOSE. \n \n1.F.5. Some states do not allow disclaimers of certain implied \nwarranties or the exclusion or limitation of certain types of \ndamages. If any disclaimer or limitation set forth in this agreement \nviolates the law of the state applicable to this agreement, ", - " If any disclaimer or limitation set forth in this agreement \nviolates the law of the state applicable to this agreement, the \nagreement shall be interpreted to make the maximum disclaimer or \nlimitation permitted by the applicable state law. The invalidity or \nunenforceability of any provision of this agreement shall not void the \nremaining provisions. \n \n1.F.6.", - "nt, and any volunteers associated with the \nproduction, promotion and distribution of Project Gutenberg\u2122 INDEMNITY - You agree to indemnify and hold the Foundation, the \ntrademark owner, any agent or employee of the Foundation,", - "INDEMNITY - You agree to indemnify and hold the Foundation, the \ntrademark owner, any agent or employee of the Foundation, anyone \nproviding copies of Project Gutenberg\u2122 electronic works in \naccordance with this agreeme electronic works, harmless from all liability, costs and expenses, \nincluding legal fees, that arise directly or indirectly from any of \nthe following which you do or cause to occur: (a) distribution of this \nor any Project Gutenberg\u2122 work, (b) alteration, modification, or \nadditions or deletions to any Project Gutenberg\u2122 work, and (c) any \nDefect you cause. \n \nSection 2. Information about the Mission of Project Gutenberg\u2122 \n \nProject Gutenberg\u2122 is synonymous with the free distribution of \nelectronic works in formats readable by the widest variety of \ncomputers including obsolete, old, middle-aged and new computers. It \nexists because of the efforts of hundreds of volunteers and donations \nfrom people in all walks of life. \n \nVolunteers and financial support to provide volunteers with the \nassistance they need are critical to reaching Project Gutenberg\u2122\u2019s \ngoals and ensuring that the Project Gutenberg\u2122 collection will \nremain freely available for generations to come.", - " In 2001, the Project \nGutenberg Literary Archive Foundation was created to provide a secure \nand permanent future for Project Gutenberg\u2122 and future \ngenerations. To learn more about the Project Gutenberg Literary \nArchive Foundation and how your efforts and donations can help, see \nSections 3 and 4 and the Foundation information page at www.gutenberg.org. \n \nSection 3. Information about the Project Gutenberg Literary Archive \nFoundation \n \nThe Project Gutenberg Literary Archive Foundation is a non-profit \n501(c)(3) educational corporation organized under the laws of the \nstate of Mississippi and granted tax exempt status by the Internal \nRevenue Service. The Foundation\u2019s EIN or federal tax identification \nnumber is 64-6221541. Contributions to the Project Gutenberg Literary \nArchive Foundation are tax deductible to the full extent permitted by \nU.S. federal laws and your state\u2019s laws. \n \nThe Foundation\u2019s business office is located at 809 North 1500 West, \nSalt Lake City, UT 84116, (801) 596-1887.", - " \n \nThe Foundation\u2019s business office is located at 809 North 1500 West, \nSalt Lake City, UT 84116, (801) 596-1887. Email contact links and up \nto date contact information can be found at the Foundation\u2019s website \nand official page at www.gutenberg.org/contact \n \nSection 4. Information about Donations to the Project Gutenberg \nLiterary Archive Foundation \n \nProject Gutenberg\u2122 depends upon and cannot survive without widespread \npublic support and donations to carry out its mission of \nincreasing the number of public domain and licensed works that can be \nfreely distributed in machine-readable form accessible by the widest \narray of equipment including outdated equipment. Many small donations \n($1 to $5,000) are particularly important to maintaining tax exempt \nstatus with the IRS. \n \nThe Foundation is committed to complying with the laws regulating \ncharities and charitable donations in all 50 states of the United \nStates. Compliance requirements are not uniform and it takes a \nconsiderable effort, much paperwork and many fees to meet and keep ", - " Compliance requirements are not uniform and it takes a \nconsiderable effort, much paperwork and many fees to meet and keep up \nwith these requirements. We do not solicit donations in locations \nwhere we have not received written confirmation of compliance. To SEND \nDONATIONS or determine the status of compliance for any particular state \nvisit www.gutenberg.org/donate. \n ", - "While we cannot and do not solicit contributions from states where we \nhave not met the solicitation requirements, we know of no prohibition \nagainst accepting unsolicited donations from donors in such states who \napproach us with offers to donate. \n \nInternational donations are gratefully accepted, but we cannot make \nany statements concerning tax treatment of donations received from \noutside the United States. U.S. laws alone swamp our small staff. \n \nPlease check the Project Gutenberg web pages for current donation \nmethods and addresses. Donations are accepted in a number of other \nways including checks, online payments and credit card donations. To \ndonate, please visit: www.gutenberg.org/donate. \n \nSection 5. General Information About Project Gutenberg\u2122 electronic works \n \nProfessor Michael S. Hart was the originator of the Project \nGutenberg\u2122 concept of a library of electronic works that could be \nfreely shared with anyone. For forty years, he produced and \ndistributed Project Gutenberg\u2122 eBooks with only a loose network of \nvolunteer support.", - " For forty years, he produced and \ndistributed Project Gutenberg\u2122 eBooks with only a loose network of \nvolunteer support. \n \nProject Gutenberg\u2122 eBooks are often created from several printed \neditions, all of which are confirmed as not protected by copyright in \nthe U.S. unless a copyright notice is included. Thus, we do not \nnecessarily keep eBooks in compliance with any particular paper \nedition. \n \nMost people start at our website which has the main PG search \nfacility: www.gutenberg.org. \n \nThis website includes information about Project Gutenberg\u2122, \nincluding how to make donations to the Project Gutenberg Literary \nArchive Foundation, how to help produce our new eBooks, and how to \nsubscribe to our email newsletter to hear about new eBooks. \n \n \n " - ], "role_library.pdf": [ " \n \n \nRoles Descriptions at \nContoso Electronics \n \n \n \n \n \n \n", "This document contains information generated using a language model (Azure OpenAI). The \ninformation contained in this document is only for demonstration purposes and does not \nreflect the opinions or beliefs of Microsoft. Microsoft makes no representations or \nwarranties of any kind, express or implied, about the completeness, accuracy, reliability, \nsuitability or availability with respect to the information contained in this document. \nAll rights reserved to Microsoft \n ", diff --git a/tests/test_prepdocslib_filestrategy.py b/tests/test_prepdocslib_filestrategy.py index c6ca912c60..882832e739 100644 --- a/tests/test_prepdocslib_filestrategy.py +++ b/tests/test_prepdocslib_filestrategy.py @@ -74,7 +74,6 @@ async def mock_upload_documents(self, documents): "content": "texttext", "category": None, "groups": ["A-GROUP-ID"], - "images": [], "oids": ["A-USER-ID"], "sourcepage": "a.txt", "sourcefile": "a.txt", @@ -85,7 +84,6 @@ async def mock_upload_documents(self, documents): "content": "texttext", "category": None, "groups": ["B-GROUP-ID"], - "images": [], "oids": ["B-USER-ID"], "sourcepage": "b.txt", "sourcefile": "b.txt", @@ -96,7 +94,6 @@ async def mock_upload_documents(self, documents): "content": "texttext", "category": None, "groups": ["C-GROUP-ID"], - "images": [], "oids": ["C-USER-ID"], "sourcepage": "c.txt", "sourcefile": "c.txt", diff --git a/tests/test_searchmanager.py b/tests/test_searchmanager.py index 6b60e68e16..f7d95c5d27 100644 --- a/tests/test_searchmanager.py +++ b/tests/test_searchmanager.py @@ -15,6 +15,7 @@ from prepdocslib.embeddings import AzureOpenAIEmbeddingService from prepdocslib.listfilestrategy import File +from prepdocslib.page import ImageOnPage from prepdocslib.searchmanager import SearchManager, Section from prepdocslib.strategy import SearchInfo from prepdocslib.textsplitter import Chunk @@ -345,6 +346,54 @@ async def mock_upload_documents(self, documents): assert "images" not in documents_uploaded[0], "'images' field should not be present when search_images is False" +@pytest.mark.asyncio +async def test_update_content_with_images_when_enabled(monkeypatch, search_info): + """Ensure 'images' field is added with image metadata when search_images is True and chunk has images.""" + + documents_uploaded: list[dict] = [] + + async def mock_upload_documents(self, documents): + documents_uploaded.extend(documents) + + monkeypatch.setattr(SearchClient, "upload_documents", mock_upload_documents) + + # Enable image ingestion + manager = SearchManager(search_info, search_images=True) + + test_io = io.BytesIO(b"img content") + test_io.name = "test/foo.pdf" + file = File(test_io) + + image = ImageOnPage( + bytes=b"", # raw image bytes not needed for this test + bbox=(1.0, 2.0, 3.0, 4.0), + filename="img1.png", + description="Test image", + figure_id="fig1", + page_num=0, + url="http://example.com/img1.png", + embedding=[0.01, 0.02], + ) + + section = Section( + chunk=Chunk(page_num=0, text="chunk text with image", images=[image]), + content=file, + category="test", + ) + + await manager.update_content([section]) + + assert len(documents_uploaded) == 1, "Exactly one document should be uploaded" + doc = documents_uploaded[0] + assert "images" in doc, "'images' field should be present when search_images is True" + assert isinstance(doc["images"], list) and len(doc["images"]) == 1, "Should have one image entry" + img_entry = doc["images"][0] + assert img_entry["url"] == image.url + assert img_entry["description"] == image.description + assert img_entry["boundingbox"] == image.bbox + assert img_entry["embedding"] == image.embedding + + class AsyncSearchResultsIterator: def __init__(self, results): self.results = results