From c54dc179892d76236b9cdc5675d03dd0049dd371 Mon Sep 17 00:00:00 2001 From: timothyafolami Date: Thu, 8 Aug 2024 14:58:44 +0100 Subject: [PATCH] image text extraction completed --- .gitignore | 3 + __pycache__/text_extractor.cpython-311.pyc | Bin 0 -> 7567 bytes audio_experiment.ipynb | 0 data/documents.json | 2 +- .../__pycache__/utils.cpython-311.pyc | Bin 9882 -> 11516 bytes data_ingestion/utils.py | 32 +++- image_experiment.ipynb | 161 ++++++++++++++++++ loggings/app.log | 30 ++++ requirements.txt | 4 +- text_extractor.py | 4 +- vec-db/index/faiss_index_data/index.faiss | Bin 960045 -> 984621 bytes vec-db/index/faiss_index_data/index.pkl | Bin 980491 -> 982775 bytes video_experiment.ipynb | 102 +++++++++++ 13 files changed, 331 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 __pycache__/text_extractor.cpython-311.pyc create mode 100644 audio_experiment.ipynb create mode 100644 image_experiment.ipynb create mode 100644 video_experiment.ipynb diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0fe238ac --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Ai indexing +data +images \ No newline at end of file diff --git a/__pycache__/text_extractor.cpython-311.pyc b/__pycache__/text_extractor.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34fe646c72a3d6863dcf087d7ecf448c182aa1df GIT binary patch literal 7567 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 QX>-&;=1mCC0V6X03)Fd4d;kCd delta 2256 zcmbVNeQZ-z6o2=9b$%+1pH3v#V#DAc8;~VE zZ~`n(p}AiBAMoZIC|j}KTdKSF?iC6B39 zAeK*1#VglqvQ;ve+@$xV@;Ot_nU*uFn@O59lbVaw;glFZsIDY2{;j&UtP&N8S%~tb z_VXmjRmayP!M}5~Ry5;~24L6#V$fJ6uX6^~MbKR^@qn|IY-k5jvoYLEHXlLwTTs+4 zgg?tk^QrB90PJr5(88a|Cn;J8v!N^yXZOKC2Y=VKp4`g=?!%;=zvYfNg^8A2h~n6e00L?IY;hCks&uRn+apWkc2@1fIXn)on5WC&_keG!~ZBb0HLqs@RNQ^p4-ma!0h%p zD%D+N5AUvShO@|3FCN(fqb!4v1<=YYId52wOxiGMnpw8Nq`BF$4dl}~OEm^FX_H~D zuttP9LN|b=vSe7IL ztZGF^f(UZ3Z2jqs&bIO`k#M*PhmfA-LU(;QWRZT>#g9fJko_M->OIfEa2kHb&ocip zvesFq&YzJ0cz4Y^Ipla);xBn*cJwthhT9$Ll=u+nuO;S+?#Bmx7uN;&uamW5f2F;&E z^O9|P%FMGq13)iQaf;%HOY8#+!v%n43)_QmA+IFD>Z_o8gWpJ8B*BT#>W4`J!(w|7 z_5$1y1!#88=dDdq{%gFV{2W@nh=3unm-u*N+haW_-U@~;fa&bv}Sh~t=->=gvT z(+QFwS)|$6RIeTa)mh%tbR>pLUBv>N!pbt+R1mQL%Q?Q=6XlJ~@%X%9d%;$)58Nsk zMQYx((sklywOnhdeO$Z{BEMtcT60)3 z-Ds&>hjg~XB3r~$U@6H=hIPO&YXUGF05_=@%d6eclPtBFy$J*7(PA4v+M`q;_yY?&7<*_MmL-Bjb-hf)qbD5_z`xhQue9S%_Xuf1`nYOn~iSK2XcPzO#IPHqQ zW*mED%B4-onm7T-p_{367*^5}R&53@V`_6Uor4!Jn;puf%^h>GGV@`rjU3?P+Iu5; zFlA36;KNxwqXbH~Uk>q*h|7*S$ixZ1fD&Fe%Z3$#VIDC&B@rnTStPOoADQdU#o0U^ z%IKZ!G<5MqjGq8!6vD5yp5bTOc99V8m@}_t0ny&BpON72PRI~GHfK%TL0V^|e*v)x Fe*ygm4gvrG diff --git a/data_ingestion/utils.py b/data_ingestion/utils.py index 50ce4885..a4eaff52 100644 --- a/data_ingestion/utils.py +++ b/data_ingestion/utils.py @@ -8,6 +8,7 @@ from langchain_community.document_loaders import TextLoader from langchain_community.document_loaders import Docx2txtLoader from uuid import uuid4 from langchain_core.documents import Document +from text_extractor import TextExtractor import os import json @@ -90,6 +91,18 @@ def load_document(document_path): else: raise ValueError(f"Unsupported document type for {document_path}") +def create_image_document(image_path): + # getting the image name from the image path + image_name = image_path.split('/')[-1].split('.')[0] + # setting image name as metadata + metadata = {'filename': image_name} + text_extractor = TextExtractor() + text = text_extractor.read_text_from_image(image_path) + # removing special characters and line breaks + text = ''.join(e for e in text if e.isalnum() or e.isspace() or e == '\n') + doc = Document(page_content=text, metadata=metadata) + # returning the document in a list + return [doc] def save_embedded_data(embeddings, key="data"): @@ -133,6 +146,16 @@ def load_documents_from_directory(directory_path: str): # adding the document name to the doc_names list doc_names.append(doc_name) print(f"Document {doc_name} loaded") + elif extension in image_doc: + # creating an image document + doc = create_image_document(path) + # appending the document to the documents list + documents.append(doc) + # appending the number of pages in the document + num_pages.append(1) + # adding the document name to the doc_names list + doc_names.append(doc[0].metadata['filename']) + print(f"Document {doc[0].metadata['filename']} loaded") # so we need to create a document id for each document docs_id = [uuid4().hex for i in range(len(documents))] @@ -189,11 +212,14 @@ def add_documents_to_vector_store(embeddings, documents: list, docs_id: list, nu # A document search function -def search(db, query, k=4): +def search(db, query, k=3): docs = db.similarity_search(query, k) all = "" pages = [] for doc in docs: - all += f"{doc.page_content}\n" - pages.append(doc.metadata['page']) + all += f"{doc.page_content}\n" + try: + pages.append(doc.metadata['page']) + except: + pages.append(doc.metadata['filename']) return docs[0].page_content, all, pages diff --git a/image_experiment.ipynb b/image_experiment.ipynb new file mode 100644 index 00000000..9ff5adec --- /dev/null +++ b/image_experiment.ipynb @@ -0,0 +1,161 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -q pdfplumber" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "from text_extractor import TextExtractor\n", + "from langchain_core.documents import Document" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "# creating a function to extract texts from image\n", + "def create_image_document(image_path):\n", + " # getting the image name from the image path\n", + " image_name = image_path.split('/')[-1].split('.')[0]\n", + " # setting image name as metadata\n", + " metadata = {'filename': image_name}\n", + " text_extractor = TextExtractor()\n", + " text = text_extractor.read_text_from_image(image_path)\n", + " # removing special characters and line breaks\n", + " text = ''.join(e for e in text if e.isalnum() or e.isspace() or e == '\\n')\n", + " doc = Document(page_content=text, metadata=metadata)\n", + " # returning the document\n", + " return [doc]" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Document(metadata={'filename': 'IMG_1438'}, page_content='ex a\\n\\nAccidented car before repair\\n')]\n" + ] + } + ], + "source": [ + "# testing the function\n", + "image_path = 'data/IMG_1438.jpeg'\n", + "text = create_image_document(image_path)\n", + "print(text)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'filename': 'IMG_1438'}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text[0].metadata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "smog_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/loggings/app.log b/loggings/app.log index 83cf54b1..35d6d571 100644 --- a/loggings/app.log +++ b/loggings/app.log @@ -50,3 +50,33 @@ 2024-08-07 18:46:38,939 - INFO - Loading the embeddings 2024-08-07 18:46:38,939 - INFO - Load pretrained SentenceTransformer: BAAI/bge-small-en 2024-08-07 18:47:03,089 - INFO - Embeddings loaded +2024-08-08 14:03:36,111 - INFO - Loading the embeddings +2024-08-08 14:03:36,113 - INFO - Load pretrained SentenceTransformer: BAAI/bge-small-en +2024-08-08 14:03:39,637 - INFO - Embeddings loaded +2024-08-08 14:03:39,637 - INFO - Loading data from ./data +2024-08-08 14:04:29,085 - INFO - Data loaded +2024-08-08 14:04:29,087 - INFO - Creating vector store +2024-08-08 14:06:40,106 - INFO - Loading the embeddings +2024-08-08 14:06:40,106 - INFO - Load pretrained SentenceTransformer: BAAI/bge-small-en +2024-08-08 14:06:43,523 - INFO - Embeddings loaded +2024-08-08 14:06:43,523 - INFO - Loading data from ./data +2024-08-08 14:20:21,150 - INFO - Loading the embeddings +2024-08-08 14:20:21,150 - INFO - Load pretrained SentenceTransformer: BAAI/bge-small-en +2024-08-08 14:20:25,150 - INFO - Embeddings loaded +2024-08-08 14:20:25,150 - INFO - Loading data from ./data +2024-08-08 14:21:13,769 - INFO - Data loaded +2024-08-08 14:21:13,769 - INFO - Creating vector store +2024-08-08 14:21:24,386 - INFO - Vector store created +2024-08-08 14:21:24,386 - INFO - Saving the vector store +2024-08-08 14:21:24,386 - INFO - Vector store saved +2024-08-08 14:22:17,106 - INFO - Receiving the search query +2024-08-08 14:22:23,740 - INFO - Searching for Accidented car before repair +2024-08-08 14:24:45,013 - INFO - Receiving the search query +2024-08-08 14:25:07,699 - INFO - Searching for Accidented car before repair +2024-08-08 14:28:43,776 - INFO - Receiving the search query +2024-08-08 14:28:46,944 - INFO - Searching for Accidented car before repair +2024-08-08 14:29:13,295 - INFO - Receiving the search query +2024-08-08 14:29:17,628 - INFO - Searching for Accidented car before repair +2024-08-08 14:29:17,820 - INFO - Search completed +2024-08-08 14:29:17,820 - INFO - Page content: Accidented car Before repair + diff --git a/requirements.txt b/requirements.txt index 5f3958d6..6db0dfa7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,6 @@ langchain-text-splitters unstructured[all-docs] docx2txt docx -"fastapi[standard]" \ No newline at end of file +fastapi[standard] +pdfplumber +pytesseract \ No newline at end of file diff --git a/text_extractor.py b/text_extractor.py index efd435e9..82d4572a 100644 --- a/text_extractor.py +++ b/text_extractor.py @@ -44,8 +44,8 @@ class TextExtractor: except Exception as e: print(f"Error reading text from image: {e}") return "" - finally: - os.remove(image_path) + # finally: + # os.remove(image_path) def read_text_from_pdf(self, pdf_path): """ diff --git a/vec-db/index/faiss_index_data/index.faiss b/vec-db/index/faiss_index_data/index.faiss index cdb06fcde81384690635ded6b260acb54adaf640..163e591de083fb9cd7a29a3333ca6c688fac8fe2 100644 GIT binary patch delta 24840 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 delta 69 zcmZ46W3%>*6{lx~n^6NJ14H3NPFcp4jq0uHjIHWSt?JCJ>MX75tgY&7t?KNp>Kv`= ZoUQ6yt?JyZ>O5Q3dD(s}*Ja^b2LQk%6F&d| diff --git a/vec-db/index/faiss_index_data/index.pkl b/vec-db/index/faiss_index_data/index.pkl index 4d6c0f41a1cb5497ce6c6cc41336db6a4e3daa1f..cc9c1998096e13fc182655ccb18fb9ddf819be5f 100644 GIT binary patch delta 37524 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 delta 35411 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