tech5 commited on
Commit
7487fcf
·
1 Parent(s): 66a0a8c

Update RAG backend and gitignore

Browse files
.gitignore ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Python
3
+ __pycache__/
4
+ *.py[cod]
5
+ *.pyo
6
+ *.pyd
7
+ *.egg-info/
8
+ .eggs/
9
+
10
+
11
+ # Virtual Environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+ ENV/
16
+
17
+
18
+ # Environment Variables
19
+ .env
20
+ .env.*
21
+ *.key
22
+
23
+
24
+ # Jupyter
25
+ .ipynb_checkpoints/
26
+
27
+
28
+ # Logs
29
+ *.log
30
+
31
+
32
+ # OS Files
33
+ .DS_Store
34
+ Thumbs.db
35
+
36
+
37
+ # IDE / Editor
38
+ .vscode/
39
+ .idea/
40
+ *.swp
41
+
42
+
43
+ # Uploaded / User Files
44
+ upload/
45
+ uploads/
46
+ *.pdf
47
+
48
+
49
+ # Vector Stores (FAISS)
50
+ faiss_index/
51
+ vectorstore/
52
+ *.faiss
53
+ *.pkl
54
+
55
+
56
+ # Streamlit
57
+ .streamlit/secrets.toml
58
+
59
+
60
+ # Cache / Temp
61
+ .cache/
62
+ tmp/
63
+ temp/
64
+
65
+
66
+ # Build / Distribution
67
+ build/
68
+ dist/
backend/__pycache__/api.cpython-310.pyc DELETED
Binary file (3.67 kB)
 
backend/api.py CHANGED
@@ -21,8 +21,6 @@ def get_vectorstore():
21
  return load_documents(embedding_model=get_embeddings())
22
 
23
 
24
-
25
-
26
  BASE_DIR = Path("/app")
27
  upload_dir = BASE_DIR / "uploads"
28
  upload_dir.mkdir(parents=True, exist_ok=True)
@@ -50,12 +48,6 @@ system_stats = {
50
  "start_time": datetime.now().isoformat()
51
  }
52
 
53
- @app.on_event("startup")
54
- def startup_event():
55
- print("🔄 Preloading embedding model...")
56
- get_embeddings()
57
- print("✅ Embedding model loaded")
58
-
59
  # Info about API
60
  @app.get("/")
61
  async def root():
@@ -112,33 +104,28 @@ async def get_stats():
112
  # This Endpoint upload Pdf and store into VectorDatabase
113
  @app.post("/upload")
114
  async def upload_file(file: UploadFile = File(...)):
115
- try:
116
- if not file.filename.endswith(".pdf"):
117
- raise HTTPException(status_code=400, detail="Only PDF files are supported")
118
 
119
- file_path = upload_dir / file.filename
120
 
121
- with open(file_path, "wb") as f:
122
- shutil.copyfileobj(file.file, f)
123
 
124
- chunked_docs = get_chunked_docs(file_path)
125
 
126
- if not chunked_docs:
127
- raise HTTPException(status_code=500, detail="No content extracted from PDF")
128
 
129
- store_documents(chunked_docs, get_embeddings())
130
-
131
- system_stats["total_uploads"] += 1
132
-
133
- return {
134
- "message": "PDF uploaded and indexed successfully",
135
- "chunks_created": len(chunked_docs)
136
- }
137
-
138
- except Exception as e:
139
- print("❌ UPLOAD ERROR:", str(e)) # <-- shows in HF logs
140
- raise HTTPException(status_code=500, detail=str(e))
141
 
 
 
 
 
142
 
143
  from pydantic import BaseModel
144
 
 
21
  return load_documents(embedding_model=get_embeddings())
22
 
23
 
 
 
24
  BASE_DIR = Path("/app")
25
  upload_dir = BASE_DIR / "uploads"
26
  upload_dir.mkdir(parents=True, exist_ok=True)
 
48
  "start_time": datetime.now().isoformat()
49
  }
50
 
 
 
 
 
 
 
51
  # Info about API
52
  @app.get("/")
53
  async def root():
 
104
  # This Endpoint upload Pdf and store into VectorDatabase
105
  @app.post("/upload")
106
  async def upload_file(file: UploadFile = File(...)):
107
+ if not file.filename.endswith(".pdf"):
108
+ raise HTTPException(status_code=400, detail="Only PDF files are supported")
 
109
 
110
+ file_path = upload_dir / file.filename
111
 
112
+ with open(file_path, "wb") as f:
113
+ shutil.copyfileobj(file.file, f)
114
 
115
+ chunked_docs = get_chunked_docs(file_path)
116
 
117
+ if not chunked_docs:
118
+ raise HTTPException(status_code=500, detail="No content extracted from PDF")
119
 
120
+ store_documents(chunked_docs, get_embeddings())
121
+
122
+ # INCREMENT THE COUNTER HERE!
123
+ system_stats["total_uploads"] += 1
 
 
 
 
 
 
 
 
124
 
125
+ return {
126
+ "message": "PDF uploaded and indexed successfully",
127
+ "chunks_created": len(chunked_docs)
128
+ }
129
 
130
  from pydantic import BaseModel
131
 
rag/__pycache__/chain.cpython-310.pyc DELETED
Binary file (2.75 kB)
 
rag/__pycache__/combine.cpython-310.pyc DELETED
Binary file (1.3 kB)
 
rag/__pycache__/lang_doc.cpython-310.pyc DELETED
Binary file (453 Bytes)
 
rag/__pycache__/lc.cpython-310.pyc DELETED
Binary file (447 Bytes)
 
rag/__pycache__/rag.cpython-310.pyc DELETED
Binary file (2.75 kB)
 
rag/__pycache__/smark_chunking.cpython-310.pyc DELETED
Binary file (1.06 kB)
 
rag/__pycache__/smart_chunking.cpython-310.pyc DELETED
Binary file (1.07 kB)
 
rag/chain.py CHANGED
@@ -50,6 +50,7 @@ prompt = ChatPromptTemplate.from_template(
50
  Answer the question strictly using the information contained in the document excerpts below.
51
  Do not mention the phrases "provided context", "given context", or similar meta-references.
52
  Do not include conversational language or assumptions.
 
53
 
54
  Writing guidelines:
55
  - Use a formal, neutral, and analytical tone.
@@ -57,12 +58,6 @@ Writing guidelines:
57
  - If information is missing, clearly state that it is not available in the document.
58
  - Do not speculate or add external knowledge.
59
 
60
- Citation rules:
61
- - List citations in a separate section highlighted with blue.
62
- - Each citation must include page number and table/figure/image reference if available.
63
- - Use this format exactly:
64
- • Page X, Table/Figure/Image Y (if applicable)
65
-
66
  <Document Excerpts>
67
  {context}
68
  </Document Excerpts>
@@ -71,7 +66,6 @@ Question:
71
  {input}
72
  """
73
  )
74
-
75
  # Get Retrieval chain
76
  def get_rag_chain(retriever):
77
  chain = (
 
50
  Answer the question strictly using the information contained in the document excerpts below.
51
  Do not mention the phrases "provided context", "given context", or similar meta-references.
52
  Do not include conversational language or assumptions.
53
+ Do not use any HTML tags or formatting in your response.
54
 
55
  Writing guidelines:
56
  - Use a formal, neutral, and analytical tone.
 
58
  - If information is missing, clearly state that it is not available in the document.
59
  - Do not speculate or add external knowledge.
60
 
 
 
 
 
 
 
61
  <Document Excerpts>
62
  {context}
63
  </Document Excerpts>
 
66
  {input}
67
  """
68
  )
 
69
  # Get Retrieval chain
70
  def get_rag_chain(retriever):
71
  chain = (
rag/combine.py CHANGED
@@ -4,13 +4,20 @@ import camelot
4
  import pytesseract
5
  from PIL import Image
6
  import io
 
 
 
 
 
 
 
 
7
 
8
 
9
  # Raw Documents
10
  def raw_document_text(pdf_path: str):
11
  documents = []
12
 
13
- # Open PDF
14
  with pdfplumber.open(pdf_path) as pdf:
15
  doc_fitz = fitz.open(pdf_path)
16
 
@@ -20,14 +27,13 @@ def raw_document_text(pdf_path: str):
20
  text = page.extract_text()
21
  if text:
22
  documents.append({
23
- "content": text,
24
  "metadata": {
25
  "page": page_index,
26
  "type": "text"
27
  }
28
  })
29
 
30
-
31
  # TABLES
32
  tables = camelot.read_pdf(
33
  pdf_path,
@@ -38,7 +44,7 @@ def raw_document_text(pdf_path: str):
38
  for t_idx, table in enumerate(tables):
39
  table_text = table.df.to_string(index=False)
40
  documents.append({
41
- "content": table_text,
42
  "metadata": {
43
  "page": page_index,
44
  "type": "table",
@@ -46,7 +52,6 @@ def raw_document_text(pdf_path: str):
46
  }
47
  })
48
 
49
-
50
  # IMAGES + OCR
51
  page_fitz = doc_fitz[page_index - 1]
52
  images = page_fitz.get_images(full=True)
@@ -61,7 +66,7 @@ def raw_document_text(pdf_path: str):
61
 
62
  if ocr_text.strip():
63
  documents.append({
64
- "content": ocr_text,
65
  "metadata": {
66
  "page": page_index,
67
  "type": "image",
@@ -69,6 +74,4 @@ def raw_document_text(pdf_path: str):
69
  }
70
  })
71
 
72
- return documents
73
-
74
-
 
4
  import pytesseract
5
  from PIL import Image
6
  import io
7
+ import re
8
+
9
+
10
+ def clean_text(text: str) -> str:
11
+ text = re.sub(r'<[^>]+>', '', text) # strip <font>, <b>, <i>, etc.
12
+ text = re.sub(r'[ \t]+', ' ', text) # normalize spaces/tabs
13
+ text = re.sub(r'\n{3,}', '\n\n', text) # collapse excessive newlines
14
+ return text.strip()
15
 
16
 
17
  # Raw Documents
18
  def raw_document_text(pdf_path: str):
19
  documents = []
20
 
 
21
  with pdfplumber.open(pdf_path) as pdf:
22
  doc_fitz = fitz.open(pdf_path)
23
 
 
27
  text = page.extract_text()
28
  if text:
29
  documents.append({
30
+ "content": clean_text(text),
31
  "metadata": {
32
  "page": page_index,
33
  "type": "text"
34
  }
35
  })
36
 
 
37
  # TABLES
38
  tables = camelot.read_pdf(
39
  pdf_path,
 
44
  for t_idx, table in enumerate(tables):
45
  table_text = table.df.to_string(index=False)
46
  documents.append({
47
+ "content": clean_text(table_text),
48
  "metadata": {
49
  "page": page_index,
50
  "type": "table",
 
52
  }
53
  })
54
 
 
55
  # IMAGES + OCR
56
  page_fitz = doc_fitz[page_index - 1]
57
  images = page_fitz.get_images(full=True)
 
66
 
67
  if ocr_text.strip():
68
  documents.append({
69
+ "content": clean_text(ocr_text),
70
  "metadata": {
71
  "page": page_index,
72
  "type": "image",
 
74
  }
75
  })
76
 
77
+ return documents
 
 
rag/smart_search.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import defaultdict
2
+
3
+ from langchain_core.documents import Document
4
+
5
+
6
+ # Raw Documents to Langchain Documents
7
+ def get_langchain_docs(docs:str):
8
+ lc_docs = []
9
+ for doc in docs:
10
+ document = Document(
11
+ page_content=doc['content'],
12
+ metadata=doc['metadata']
13
+ )
14
+ lc_docs.append(document)
15
+ return lc_docs
16
+
17
+
18
+
19
+ docs = {
20
+ 1: "Artificial intelligence and machine learning are transforming modern software systems by enabling automated decision making and intelligent data analysis.",
21
+ 2: "Smart parking systems use sensors, real time data processing, and predictive analytics to efficiently allocate parking slots and reduce traffic congestion in urban cities.",
22
+ 3: "Data science combines statistics, programming, and domain knowledge to extract meaningful insights from large datasets for business and research applications."
23
+ }
24
+
25
+
26
+ index = defaultdict(set)
27
+ for doc_id, text in docs.items():
28
+ words = text.lower().split()
29
+ for word in words:
30
+ index[word].add(doc_id)
31
+
32
+
33
+ class TrieNode:
34
+ def __init__(self):
35
+ self.children = {}
36
+ self.is_end = False
37
+
38
+ class Trie:
39
+ def __init__(self):
40
+ self.root = TrieNode()
41
+
42
+ def insert(self, word):
43
+ node = self.root
44
+ for ch in word:
45
+ if ch not in node.children:
46
+ node.children[ch] = TrieNode()
47
+ node = node.children[ch]
48
+ node.is_end = True
49
+
50
+ def autocomplete(prefix):
51
+ results = []
52
+ trie = Trie()
53
+ for text in docs.values():
54
+ for word in text.split():
55
+ trie.insert(word)
56
+
57
+ def dfs(node, path):
58
+ if node.is_end:
59
+ results.append(path)
60
+ for ch, nxt in node.children.items():
61
+ dfs(nxt, path + ch)
62
+
63
+ node = trie.root
64
+ for ch in prefix:
65
+ if ch not in node.children:
66
+ return []
67
+ node = node.children[ch]
68
+
69
+ dfs(node, prefix)
70
+ return results
71
+
72
+ def auto_complete(query):
73
+ result = []
74
+
75
+ for q in query.split():
76
+ try:
77
+ result.append(autocomplete(q)[0])
78
+ except IndexError:
79
+ continue
80
+
81
+ return " ".join(result)
82
+
83
+ def ranked_search(query):
84
+ words = query.lower().split()
85
+ score = {}
86
+
87
+ for w in words:
88
+ for doc in index[w]:
89
+ score[doc] = score.get(doc, 0) + 1
90
+
91
+ return sorted(score.items(), key=lambda x: x[1], reverse=True)
92
+
93
+ def get_doc(query):
94
+ ranked = ranked_search(query)
95
+ docs = []
96
+ if len(ranked)>0:
97
+ for i in range(len(ranked)):
98
+ docs.append(ranked[i][0])
99
+ return docs[:2]
100
+
101
+ query = "Smar par system combines Data science statistics"
102
+ def final_docs_Search(query):
103
+ sent = auto_complete(query)
104
+ result = get_doc(sent)
105
+ return result
106
+
107
+ print(final_docs_Search(query))