syzdekbr commited on
Commit
ab7ac15
·
verified ·
1 Parent(s): ed9825a

Create combined_pipeline.py

Browse files
Files changed (1) hide show
  1. combined_pipeline.py +70 -0
combined_pipeline.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # combined_pipeline.py
2
+ import os, subprocess
3
+ from sentence_transformers import CrossEncoder
4
+ import fitz
5
+ import pandas as pd
6
+ from langchain_community.embeddings import HuggingFaceEmbeddings
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import Chroma
9
+ from langchain.docstore.document import Document
10
+
11
+ def extract_styled_blocks(pdf_path):
12
+ doc = fitz.open(pdf_path)
13
+ pages = []
14
+ for page_num, page in enumerate(doc):
15
+ blocks = page.get_text("dict")["blocks"]
16
+ for block in blocks:
17
+ if "lines" in block:
18
+ for line in block["lines"]:
19
+ for span in line["spans"]:
20
+ pages.append({
21
+ "text": span["text"].strip(),
22
+ "is_bold": "Bold" in span["font"],
23
+ "is_italic": "Italic" in span["font"],
24
+ "page": page_num + 1
25
+ })
26
+ return pages
27
+
28
+ def parse_pdf_with_headings(pdf_path):
29
+ spans = extract_styled_blocks(pdf_path)
30
+ docs, cur_h, cur_s = [], "No heading", None
31
+ for span in spans:
32
+ t = span["text"]
33
+ if not t:
34
+ continue
35
+ if span["is_bold"] and len(t) > 3:
36
+ cur_h, cur_s = t, None
37
+ elif span["is_italic"] and len(t) > 3:
38
+ cur_s = t
39
+ docs.append(Document(page_content=t, metadata={"page": span["page"], "heading": cur_h, "subheading": cur_s}))
40
+ return docs
41
+
42
+ def run_rag(pdf_path, df_items):
43
+ raw = parse_pdf_with_headings(pdf_path)
44
+ splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
45
+ docs = splitter.split_documents(raw)
46
+
47
+ embedder = HuggingFaceEmbeddings(model_name="nomic-ai/nomic-embed-text-v1", model_kwargs={"trust_remote_code": True})
48
+ vectordb = Chroma.from_documents(documents=docs, embedding=embedder, persist_directory="/tmp/chroma_db")
49
+
50
+ reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
51
+ results = []
52
+ for idx, row in df_items.iterrows():
53
+ query = row["item"]
54
+ tops = vectordb.similarity_search_with_score(query, k=10)
55
+ inps = [[query, d.page_content] for d, _ in tops]
56
+ scores = reranker.predict(inps)
57
+ ranked = sorted(zip(scores, tops), key=lambda x: x[0], reverse=True)[:3]
58
+ pages = [d.metadata["page"] for _, (d, _) in ranked]
59
+ headings = [d.metadata["heading"] for _, (d, _) in ranked]
60
+ subs = [d.metadata.get("subheading") or "" for _, (d, _) in ranked]
61
+ results.append({
62
+ "item_title": row["item_title"],
63
+ **{f"sim_{i+1}": pages[i] for i in range(3)},
64
+ **{f"heading_{i+1}": headings[i] for i in range(3)},
65
+ **{f"subheading_{i+1}": subs[i] for i in range(3)},
66
+ **{f"rerank_score_{i+1}": round(ranked[i][0], 2) for i in range(3)}
67
+ })
68
+
69
+ vectordb.delete_collection()
70
+ return pd.DataFrame(results)