daniel-simeone commited on
Commit
fbbc5a8
·
1 Parent(s): 5618d45

add in title info

Browse files
Files changed (2) hide show
  1. app.py +10 -6
  2. ingestion.py +36 -3
app.py CHANGED
@@ -204,12 +204,15 @@ class RAGChatbot:
204
  try:
205
  results = self.ingestion.search(query, k=num_results)
206
  if results:
207
- # Build context from retrieved chunks
208
  context_parts = []
209
  for i, result in enumerate(results, 1):
210
  text = result['text'].strip()
211
- if text:
212
- context_parts.append(f"[Context {i}]\n{text}")
 
 
 
213
 
214
  context = "\n\n".join(context_parts)
215
 
@@ -229,8 +232,8 @@ Do not reveal your internal reasoning. Provide only the final answer.
229
 
230
  Structure your answer in the following format:
231
  Summary — A brief, high‑level answer.
232
- Supporting Details — Explain using information only from the provided context.
233
- Context References — Quote or cite the exact context segments that support your answer (if applicable). Context reference should include the title of the document referred to.
234
 
235
  Context:
236
  {context}
@@ -260,7 +263,8 @@ Answer:"""
260
  response_parts = []
261
  response_parts.append("I retrieved relevant information, but couldn't generate a synthesized answer. Here are the relevant chunks:\n\n")
262
  for i, result in enumerate(results, 1):
263
- source = result['metadata']['source']
 
264
  text = result['text'].strip()
265
  if text:
266
  response_parts.append(f"**Relevant information {i}** (from {source}):\n{text}\n")
 
204
  try:
205
  results = self.ingestion.search(query, k=num_results)
206
  if results:
207
+ # Build context from retrieved chunks; include source/title so the model can cite it
208
  context_parts = []
209
  for i, result in enumerate(results, 1):
210
  text = result['text'].strip()
211
+ if not text:
212
+ continue
213
+ meta = result.get('metadata') or {}
214
+ source_label = meta.get('document_title') or meta.get('source') or f"Source {i}"
215
+ context_parts.append(f"[Context {i}] (Source: {source_label})\n{text}")
216
 
217
  context = "\n\n".join(context_parts)
218
 
 
232
 
233
  Structure your answer in the following format:
234
  Summary — A brief, high‑level answer.
235
+ Supporting Details — Explain using information only from the provided context. When citing, use the Source label shown for that context (e.g. the document title or name in parentheses after [Context N]).
236
+ Context References — List each reference with the exact Source shown for that context (e.g. "CAN/CGSB-32.312-2018" or the document title). Include section name or page when that information appears in the context text. Format: document/source, section or location if available, and a short quote or paraphrase. Do not use only "Context 1" or "Context 5" as the reference; always include the document title/source.
237
 
238
  Context:
239
  {context}
 
263
  response_parts = []
264
  response_parts.append("I retrieved relevant information, but couldn't generate a synthesized answer. Here are the relevant chunks:\n\n")
265
  for i, result in enumerate(results, 1):
266
+ meta = result.get('metadata') or {}
267
+ source = meta.get('document_title') or meta.get('source', '')
268
  text = result['text'].strip()
269
  if text:
270
  response_parts.append(f"**Relevant information {i}** (from {source}):\n{text}\n")
ingestion.py CHANGED
@@ -34,6 +34,30 @@ class DocumentIngestion:
34
  self.embeddings = None
35
  self.index = None
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  def read_pdf(self, file_path: str) -> str:
38
  """
39
  Extract text from a PDF file.
@@ -108,14 +132,14 @@ class DocumentIngestion:
108
  if not os.path.exists(pdf_path):
109
  print(f"Warning: PDF file not found: {pdf_path}")
110
  continue
111
-
112
  text = self.read_pdf(pdf_path)
113
  chunks = self.text_splitter.split_text(text)
114
-
115
  for i, chunk in enumerate(chunks):
116
  all_texts.append(chunk)
117
  all_metadata.append({
118
  'source': pdf_path,
 
119
  'type': 'pdf',
120
  'chunk_index': i
121
  })
@@ -126,11 +150,20 @@ class DocumentIngestion:
126
  try:
127
  text = self.read_url(url)
128
  chunks = self.text_splitter.split_text(text)
129
-
 
 
 
 
 
 
 
 
130
  for i, chunk in enumerate(chunks):
131
  all_texts.append(chunk)
132
  all_metadata.append({
133
  'source': url,
 
134
  'type': 'url',
135
  'chunk_index': i
136
  })
 
34
  self.embeddings = None
35
  self.index = None
36
 
37
+ def get_pdf_document_title(self, file_path: str) -> str:
38
+ """
39
+ Get a human-readable document title for a PDF (from metadata or filename).
40
+
41
+ Args:
42
+ file_path: Path to the PDF file
43
+
44
+ Returns:
45
+ Document title (e.g. standard name or filename without extension)
46
+ """
47
+ try:
48
+ reader = PdfReader(file_path)
49
+ if reader.metadata and getattr(reader.metadata, "title", None):
50
+ title = reader.metadata.title
51
+ if title and title.strip():
52
+ return title.strip()
53
+ except Exception:
54
+ pass
55
+ # Fallback: filename without extension, cleaned for standards (e.g. CAN-CGSB-32.312 -> CAN/CGSB-32.312)
56
+ base = os.path.splitext(os.path.basename(file_path))[0]
57
+ if base:
58
+ return base.replace("-", "/") if "CGSB" in base or "CAN" in base else base
59
+ return file_path
60
+
61
  def read_pdf(self, file_path: str) -> str:
62
  """
63
  Extract text from a PDF file.
 
132
  if not os.path.exists(pdf_path):
133
  print(f"Warning: PDF file not found: {pdf_path}")
134
  continue
135
+ document_title = self.get_pdf_document_title(pdf_path)
136
  text = self.read_pdf(pdf_path)
137
  chunks = self.text_splitter.split_text(text)
 
138
  for i, chunk in enumerate(chunks):
139
  all_texts.append(chunk)
140
  all_metadata.append({
141
  'source': pdf_path,
142
+ 'document_title': document_title,
143
  'type': 'pdf',
144
  'chunk_index': i
145
  })
 
150
  try:
151
  text = self.read_url(url)
152
  chunks = self.text_splitter.split_text(text)
153
+ # Use a short label for URL (domain + path hint) as document_title
154
+ try:
155
+ from urllib.parse import urlparse
156
+ parsed = urlparse(url)
157
+ document_title = parsed.netloc or url
158
+ if parsed.path and parsed.path != "/":
159
+ document_title += " " + parsed.path.strip("/")[:50]
160
+ except Exception:
161
+ document_title = url
162
  for i, chunk in enumerate(chunks):
163
  all_texts.append(chunk)
164
  all_metadata.append({
165
  'source': url,
166
+ 'document_title': document_title,
167
  'type': 'url',
168
  'chunk_index': i
169
  })