singhankur01 commited on
Commit
7ca39a5
·
verified ·
1 Parent(s): 9ab78f8

Update utils/DocsLoader.py

Browse files
Files changed (1) hide show
  1. utils/DocsLoader.py +101 -15
utils/DocsLoader.py CHANGED
@@ -1,28 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import tempfile
3
  import requests
 
 
4
 
5
  from fastapi import HTTPException
6
- # from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
7
  from langchain_community.document_loaders import PyMuPDFLoader, Docx2txtLoader
8
- from langchain.text_splitter import RecursiveCharacterTextSplitter
9
- from langchain_text_splitters.sentence_transformers import SentenceTransformersTokenTextSplitter # give better results but slow can use later for project
10
  from langchain.schema import Document
 
11
 
12
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
 
 
13
 
14
  def load_and_chunk(url: str) -> list[Document]:
15
- print(url)
16
- resp = requests.get(url)
 
 
 
 
 
 
17
  if resp.status_code != 200:
18
  raise HTTPException(400, "Could not download document")
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  content_type = resp.headers.get("Content-Type", "").lower()
21
  url_lower = url.lower()
 
22
 
23
  if "application/pdf" in content_type or ".pdf" in url_lower:
24
  with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
25
- tmp.write(resp.content)
26
  tmp_path = tmp.name
27
  try:
28
  loader = PyMuPDFLoader(tmp_path)
@@ -30,12 +111,9 @@ def load_and_chunk(url: str) -> list[Document]:
30
  finally:
31
  os.remove(tmp_path)
32
 
33
- elif (
34
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document" in content_type
35
- or ".docx" in url_lower
36
- ):
37
  with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
38
- tmp.write(resp.content)
39
  tmp_path = tmp.name
40
  try:
41
  loader = Docx2txtLoader(tmp_path)
@@ -44,12 +122,20 @@ def load_and_chunk(url: str) -> list[Document]:
44
  os.remove(tmp_path)
45
 
46
  elif "text/plain" in content_type or ".txt" in url_lower:
47
- text = resp.content.decode("utf-8", errors="ignore")
48
  docs = [Document(page_content=text)]
49
 
50
  else:
51
  raise HTTPException(400, f"Unsupported document type: {content_type}")
52
 
53
- # splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=120,separators=["\n\n", "\n", ".", " ", ""])
54
- splitter = SentenceTransformersTokenTextSplitter(model_name = MODEL_DIR,tokens_per_chunk=500, chunk_overlap=80)
55
- return splitter.split_documents(docs)
 
 
 
 
 
 
 
 
 
1
+ # import os
2
+ # import tempfile
3
+ # import requests
4
+
5
+ # from fastapi import HTTPException
6
+ # # from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
7
+ # from langchain_community.document_loaders import PyMuPDFLoader, Docx2txtLoader
8
+ # from langchain.text_splitter import RecursiveCharacterTextSplitter
9
+ # from langchain_text_splitters.sentence_transformers import SentenceTransformersTokenTextSplitter # give better results but slow can use later for project
10
+ # from langchain.schema import Document
11
+
12
+ # MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
13
+
14
+ # def load_and_chunk(url: str) -> list[Document]:
15
+ # print(url)
16
+ # resp = requests.get(url)
17
+ # if resp.status_code != 200:
18
+ # raise HTTPException(400, "Could not download document")
19
+
20
+ # content_type = resp.headers.get("Content-Type", "").lower()
21
+ # url_lower = url.lower()
22
+
23
+ # if "application/pdf" in content_type or ".pdf" in url_lower:
24
+ # with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
25
+ # tmp.write(resp.content)
26
+ # tmp_path = tmp.name
27
+ # try:
28
+ # loader = PyMuPDFLoader(tmp_path)
29
+ # docs = loader.load_and_split()
30
+ # finally:
31
+ # os.remove(tmp_path)
32
+
33
+ # elif (
34
+ # "application/vnd.openxmlformats-officedocument.wordprocessingml.document" in content_type
35
+ # or ".docx" in url_lower
36
+ # ):
37
+ # with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
38
+ # tmp.write(resp.content)
39
+ # tmp_path = tmp.name
40
+ # try:
41
+ # loader = Docx2txtLoader(tmp_path)
42
+ # docs = loader.load_and_split()
43
+ # finally:
44
+ # os.remove(tmp_path)
45
+
46
+ # elif "text/plain" in content_type or ".txt" in url_lower:
47
+ # text = resp.content.decode("utf-8", errors="ignore")
48
+ # docs = [Document(page_content=text)]
49
+
50
+ # else:
51
+ # raise HTTPException(400, f"Unsupported document type: {content_type}")
52
+
53
+ # # splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=120,separators=["\n\n", "\n", ".", " ", ""])
54
+ # splitter = SentenceTransformersTokenTextSplitter(model_name = MODEL_DIR,tokens_per_chunk=500, chunk_overlap=80)
55
+ # return splitter.split_documents(docs)
56
+
57
  import os
58
  import tempfile
59
  import requests
60
+ import hashlib
61
+ import pickle
62
 
63
  from fastapi import HTTPException
 
64
  from langchain_community.document_loaders import PyMuPDFLoader, Docx2txtLoader
 
 
65
  from langchain.schema import Document
66
+ from langchain_text_splitters.sentence_transformers import SentenceTransformersTokenTextSplitter # better but slower
67
 
68
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
69
+ CACHE_DIR = "/data/cache"
70
+ os.makedirs(CACHE_DIR, exist_ok=True)
71
 
72
  def load_and_chunk(url: str) -> list[Document]:
73
+ print(f"[Loader] Fetching: {url}")
74
+
75
+ # Get content length to decide whether to stream
76
+ head = requests.head(url)
77
+ file_size = int(head.headers.get("Content-Length", 0))
78
+ USE_STREAM = file_size > 30 * 1024 * 1024 # > 30MB
79
+
80
+ resp = requests.get(url, stream=USE_STREAM)
81
  if resp.status_code != 200:
82
  raise HTTPException(400, "Could not download document")
83
 
84
+ # Hash file content to create a unique cache key
85
+ hasher = hashlib.md5()
86
+ content = b""
87
+ for chunk in resp.iter_content(8192):
88
+ hasher.update(chunk)
89
+ content += chunk
90
+ content_hash = hasher.hexdigest()
91
+ cache_file = os.path.join(CACHE_DIR, f"{content_hash}.pkl")
92
+
93
+ # Return cached version if exists
94
+ if os.path.exists(cache_file):
95
+ print(f"✅ Loaded chunks from disk cache (key={content_hash})")
96
+ with open(cache_file, "rb") as f:
97
+ return pickle.load(f)
98
+
99
+ # Determine content type
100
  content_type = resp.headers.get("Content-Type", "").lower()
101
  url_lower = url.lower()
102
+ docs = []
103
 
104
  if "application/pdf" in content_type or ".pdf" in url_lower:
105
  with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
106
+ tmp.write(content)
107
  tmp_path = tmp.name
108
  try:
109
  loader = PyMuPDFLoader(tmp_path)
 
111
  finally:
112
  os.remove(tmp_path)
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(content)
117
  tmp_path = tmp.name
118
  try:
119
  loader = Docx2txtLoader(tmp_path)
 
122
  os.remove(tmp_path)
123
 
124
  elif "text/plain" in content_type or ".txt" in url_lower:
125
+ text = content.decode("utf-8", errors="ignore")
126
  docs = [Document(page_content=text)]
127
 
128
  else:
129
  raise HTTPException(400, f"Unsupported document type: {content_type}")
130
 
131
+ # Split the docs
132
+ splitter = SentenceTransformersTokenTextSplitter(model_name=MODEL_DIR, tokens_per_chunk=500, chunk_overlap=80)
133
+ chunks = splitter.split_documents(docs)
134
+
135
+ # Save to cache
136
+ with open(cache_file, "wb") as f:
137
+ pickle.dump(chunks, f)
138
+ print(f"💾 Chunks cached to {cache_file}")
139
+
140
+ return chunks
141
+