singhankur01 commited on
Commit
95b9827
·
verified ·
1 Parent(s): 43ce9cd

Update utils/DocsLoader.py

Browse files
Files changed (1) hide show
  1. utils/DocsLoader.py +127 -46
utils/DocsLoader.py CHANGED
@@ -2,81 +2,162 @@ import os
2
  import tempfile
3
  import requests
4
 
 
 
 
 
 
 
5
  from fastapi import HTTPException
6
- import nltk
7
  # from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
8
  from langchain_community.document_loaders import PyMuPDFLoader, Docx2txtLoader
9
  from langchain.text_splitter import RecursiveCharacterTextSplitter
10
  from langchain_text_splitters.sentence_transformers import SentenceTransformersTokenTextSplitter # give better results but slow can use later for project
11
  from langchain.schema import Document
12
  # Download NLTK sentence tokenizer
13
- NLTK_PATH = "/tmp/nltk_data"
14
- os.makedirs(NLTK_PATH, exist_ok=True)
15
- nltk.data.path.append(NLTK_PATH)
16
- nltk.download("punkt", download_dir=NLTK_PATH, quiet=True)
17
- nltk.download("punkt_tab", download_dir=NLTK_PATH, quiet=True)
18
 
19
 
20
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
21
 
22
  chunk_dict= {}
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  def load_and_chunk(url: str) -> list[Document]:
26
  print(url)
27
- if(url not in chunk_dict):
28
  print("processing new url")
29
  resp = requests.get(url)
30
  if resp.status_code != 200:
31
  raise HTTPException(400, "Could not download document")
32
-
33
  content_type = resp.headers.get("Content-Type", "").lower()
34
  url_lower = url.lower()
35
-
36
- if "application/pdf" in content_type or ".pdf" in url_lower:
37
- with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
38
- tmp.write(resp.content)
39
- tmp_path = tmp.name
40
- try:
41
  loader = PyMuPDFLoader(tmp_path)
42
  docs = loader.load_and_split()
43
- finally:
44
- os.remove(tmp_path)
45
-
46
- elif (
47
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document" in content_type
48
- or ".docx" in url_lower
49
- ):
50
- with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
51
- tmp.write(resp.content)
52
- tmp_path = tmp.name
53
- try:
54
  loader = Docx2txtLoader(tmp_path)
55
  docs = loader.load_and_split()
56
- finally:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  os.remove(tmp_path)
58
 
59
- elif "text/plain" in content_type or ".txt" in url_lower:
60
- text = resp.content.decode("utf-8", errors="ignore")
61
- docs = [Document(page_content=text)]
62
-
63
- else:
64
- raise HTTPException(400, f"Unsupported document type: {content_type}")
65
- # # --- Step 1: Sentence split ---
66
- # sentence_docs = []
67
- # for doc in docs:
68
- # sentences = nltk.sent_tokenize(doc.page_content)
69
- # for sent in sentences:
70
- # if sent.strip():
71
- # sentence_docs.append(Document(page_content=sent, metadata=doc.metadata))
72
- full_text = "\n".join([doc.page_content for doc in docs])
73
-
74
- # splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=150)
75
- splitter = SentenceTransformersTokenTextSplitter(model_name = MODEL_DIR,tokens_per_chunk=512, chunk_overlap=90)
76
- # return splitter.split_documents(docs)
77
- # return splitter.split_documents([Document(page_content=full_text)])
78
  chunk_dict[url] = splitter.create_documents([full_text])
79
- # return splitter.create_documents([full_text])
80
  return chunk_dict[url]
81
  else:
82
  print("stored chunk")
 
2
  import tempfile
3
  import requests
4
 
5
+ import pandas as pd
6
+ from PIL import Image
7
+ import pytesseract
8
+ from pptx import Presentation
9
+ import shutil
10
+
11
  from fastapi import HTTPException
12
+ # import nltk
13
  # from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
14
  from langchain_community.document_loaders import PyMuPDFLoader, Docx2txtLoader
15
  from langchain.text_splitter import RecursiveCharacterTextSplitter
16
  from langchain_text_splitters.sentence_transformers import SentenceTransformersTokenTextSplitter # give better results but slow can use later for project
17
  from langchain.schema import Document
18
  # Download NLTK sentence tokenizer
19
+ # NLTK_PATH = "/tmp/nltk_data"
20
+ # os.makedirs(NLTK_PATH, exist_ok=True)
21
+ # nltk.data.path.append(NLTK_PATH)
22
+ # nltk.download("punkt", download_dir=NLTK_PATH, quiet=True)
23
+ # nltk.download("punkt_tab", download_dir=NLTK_PATH, quiet=True)
24
 
25
 
26
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
27
 
28
  chunk_dict= {}
29
 
30
+ def load_excel(path: str) -> list[Document]:
31
+ dfs = pd.read_excel(path, sheet_name=None)
32
+ docs = []
33
+ for sheet_name, df in dfs.items():
34
+ text = df.to_csv(index=False)
35
+ docs.append(Document(page_content=text, metadata={"sheet": sheet_name}))
36
+ return docs
37
+
38
+
39
+
40
+ def load_zip(path: str, depth: int = 0, base_dir="/tmp/unzipped") -> list[Document]:
41
+ extracted_docs = []
42
+ extract_dir = os.path.join(base_dir, f"level_{depth}")
43
+ os.makedirs(extract_dir, exist_ok=True)
44
+
45
+ with zipfile.ZipFile(path, 'r') as archive:
46
+ archive.extractall(extract_dir)
47
+
48
+ for name in os.listdir(extract_dir):
49
+ file_path = os.path.join(extract_dir, name)
50
+
51
+ if name.endswith(".zip"):
52
+ extracted_docs.extend(load_zip(file_path, depth + 1, base_dir)) # Recursive call
53
+ elif name.endswith(".pdf"):
54
+ loader = PyMuPDFLoader(file_path)
55
+ extracted_docs += loader.load()
56
+ elif name.endswith(".docx"):
57
+ loader = Docx2txtLoader(file_path)
58
+ extracted_docs += loader.load()
59
+ elif name.endswith(".txt"):
60
+ with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
61
+ extracted_docs.append(Document(page_content=f.read()))
62
+ elif name.endswith((".png", ".jpg", ".jpeg")):
63
+ image = Image.open(file_path)
64
+ text = pytesseract.image_to_string(image)
65
+ extracted_docs.append(Document(page_content=text))
66
+
67
+ return extracted_docs
68
+
69
+
70
+ def load_image(path: str) -> list[Document]:
71
+ image = Image.open(path)
72
+ text = pytesseract.image_to_string(image)
73
+ return [Document(page_content=text)]
74
+
75
+ def load_pptx(path: str) -> list[Document]:
76
+ prs = Presentation(path)
77
+ full_text = []
78
+ for slide in prs.slides:
79
+ for shape in slide.shapes:
80
+ if hasattr(shape, "text"):
81
+ full_text.append(shape.text)
82
+ elif shape.shape_type == 13 and shape.image: # PICTURE shape
83
+ image = shape.image.blob
84
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as img_tmp:
85
+ img_tmp.write(image)
86
+ img_path = img_tmp.name
87
+ try:
88
+ img_text = pytesseract.image_to_string(Image.open(img_path))
89
+ if img_text.strip():
90
+ full_text.append(img_text.strip())
91
+ finally:
92
+ os.remove(img_path)
93
+ return [Document(page_content="\n".join(full_text))]
94
 
95
  def load_and_chunk(url: str) -> list[Document]:
96
  print(url)
97
+ if url not in chunk_dict:
98
  print("processing new url")
99
  resp = requests.get(url)
100
  if resp.status_code != 200:
101
  raise HTTPException(400, "Could not download document")
102
+
103
  content_type = resp.headers.get("Content-Type", "").lower()
104
  url_lower = url.lower()
105
+
106
+ try:
107
+ if "application/pdf" in content_type or ".pdf" in url_lower:
108
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
109
+ tmp.write(resp.content)
110
+ tmp_path = tmp.name
111
  loader = PyMuPDFLoader(tmp_path)
112
  docs = loader.load_and_split()
113
+
114
+ elif "application/vnd.openxmlformats-officedocument.wordprocessingml.document" in content_type or ".docx" in url_lower:
115
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
116
+ tmp.write(resp.content)
117
+ tmp_path = tmp.name
 
 
 
 
 
 
118
  loader = Docx2txtLoader(tmp_path)
119
  docs = loader.load_and_split()
120
+
121
+ elif "text/plain" in content_type or ".txt" in url_lower:
122
+ text = resp.content.decode("utf-8", errors="ignore")
123
+ docs = [Document(page_content=text)]
124
+
125
+ elif ".xlsx" in url_lower:
126
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as tmp:
127
+ tmp.write(resp.content)
128
+ tmp_path = tmp.name
129
+ docs = load_excel(tmp_path)
130
+
131
+ elif ".zip" in url_lower:
132
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as tmp:
133
+ tmp.write(resp.content)
134
+ tmp_path = tmp.name
135
+ docs = []
136
+
137
+ elif ".png" in url_lower or ".jpg" in url_lower or ".jpeg" in url_lower:
138
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
139
+ tmp.write(resp.content)
140
+ tmp_path = tmp.name
141
+ docs = load_image(tmp_path)
142
+
143
+ elif ".pptx" in url_lower:
144
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pptx") as tmp:
145
+ tmp.write(resp.content)
146
+ tmp_path = tmp.name
147
+ docs = load_pptx(tmp_path)
148
+
149
+ else:
150
+ raise HTTPException(400, f"Unsupported document type: {content_type}")
151
+
152
+ finally:
153
+ if 'tmp_path' in locals() and os.path.exists(tmp_path):
154
  os.remove(tmp_path)
155
 
156
+ full_text = "\n".join([doc.page_content for doc in docs])
157
+ splitter = SentenceTransformersTokenTextSplitter(
158
+ model_name=MODEL_DIR, tokens_per_chunk=512, chunk_overlap=90
159
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  chunk_dict[url] = splitter.create_documents([full_text])
 
161
  return chunk_dict[url]
162
  else:
163
  print("stored chunk")