manan77709 commited on
Commit
edadf88
·
1 Parent(s): 4531544

connected database and ingestion

Browse files
Files changed (2) hide show
  1. backend/app/database.py +51 -0
  2. backend/app/ingest.py +124 -0
backend/app/database.py CHANGED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import psycopg2
2
+ from psycopg2.extras import RealDictCursor
3
+ import os
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ DATABASE_URL = os.getenv("DATABASE_URL")
9
+
10
+
11
+ def get_connection():
12
+ return psycopg2.connect(DATABASE_URL, cursor_factory=RealDictCursor)
13
+
14
+
15
+ def setup_database():
16
+ conn = get_connection()
17
+ cur = conn.cursor()
18
+
19
+ cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
20
+
21
+
22
+ cur.execute("""
23
+ CREATE TABLE IF NOT EXISTS studies (
24
+ id SERIAL PRIMARY KEY,
25
+ pmid TEXT UNIQUE NOT NULL,
26
+ title TEXT,
27
+ abstract TEXT,
28
+ authors TEXT[],
29
+ year INT,
30
+ journal TEXT,
31
+ study_type TEXT,
32
+ embedding vector(384)
33
+ );
34
+ """)
35
+
36
+
37
+ cur.execute("""
38
+ CREATE INDEX IF NOT EXISTS studies_embedding_idx
39
+ ON studies
40
+ USING ivfflat (embedding vector_cosine_ops)
41
+ WITH (lists = 100);
42
+ """)
43
+
44
+ conn.commit()
45
+ cur.close()
46
+ conn.close()
47
+ print("Database setup complete.")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ setup_database()
backend/app/ingest.py CHANGED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import psycopg2
4
+ from dotenv import load_dotenv
5
+ from Bio import Entrez
6
+ from sentence_transformers import SentenceTransformer
7
+ from database import get_connection
8
+
9
+ load_dotenv()
10
+
11
+ Entrez.email = os.getenv("NCBI_EMAIL", "your@email.com")
12
+
13
+ model = SentenceTransformer("all-MiniLM-L6-v2")
14
+
15
+ SEARCH_TERMS = [
16
+ "cancer treatment",
17
+ "diabetes management",
18
+ "vaccine safety",
19
+ "vitamin supplements",
20
+ "covid treatment",
21
+ "blood pressure",
22
+ "heart disease prevention",
23
+ "antibiotic resistance",
24
+ ]
25
+
26
+
27
+ def fetch_pubmed_ids(term: str, max_results: int = 500) -> list:
28
+ handle = Entrez.esearch(db="pubmed", term=term, retmax=max_results)
29
+ record = Entrez.read(handle)
30
+ handle.close()
31
+ return record["IdList"]
32
+
33
+
34
+ def fetch_abstracts(pmids: list) -> list:
35
+ ids = ",".join(pmids)
36
+ handle = Entrez.efetch(db="pubmed", id=ids, rettype="xml", retmode="xml")
37
+ records = Entrez.read(handle)
38
+ handle.close()
39
+
40
+ papers = []
41
+ for article in records["PubmedArticle"]:
42
+ try:
43
+ medline = article["MedlineCitation"]
44
+ art = medline["Article"]
45
+
46
+ pmid = str(medline["PMID"])
47
+ title = str(art.get("ArticleTitle", ""))
48
+ abstract_text = art.get("Abstract", {}).get("AbstractText", [""])
49
+ abstract = " ".join([str(a) for a in abstract_text])
50
+ journal = str(art["Journal"]["Title"])
51
+ year = int(art["Journal"]["JournalIssue"]["PubDate"].get("Year", 0) or 0)
52
+ authors = []
53
+ for a in art.get("AuthorList", []):
54
+ name = f"{a.get('LastName', '')} {a.get('ForeName', '')}".strip()
55
+ if name:
56
+ authors.append(name)
57
+
58
+ if abstract and len(abstract) > 100:
59
+ papers.append({
60
+ "pmid": pmid,
61
+ "title": title,
62
+ "abstract": abstract,
63
+ "journal": journal,
64
+ "year": year,
65
+ "authors": authors,
66
+ })
67
+ except Exception as e:
68
+ continue
69
+
70
+ return papers
71
+
72
+
73
+ def store_papers(papers: list):
74
+ conn = get_connection()
75
+ cur = conn.cursor()
76
+ stored = 0
77
+
78
+ for paper in papers:
79
+ try:
80
+ embedding = model.encode(paper["abstract"]).tolist()
81
+
82
+ cur.execute("""
83
+ INSERT INTO studies (pmid, title, abstract, authors, year, journal, embedding)
84
+ VALUES (%s, %s, %s, %s, %s, %s, %s)
85
+ ON CONFLICT (pmid) DO NOTHING
86
+ """, (
87
+ paper["pmid"],
88
+ paper["title"],
89
+ paper["abstract"],
90
+ paper["authors"],
91
+ paper["year"],
92
+ paper["journal"],
93
+ embedding,
94
+ ))
95
+ stored += 1
96
+
97
+ except Exception as e:
98
+ print(f"Error storing {paper['pmid']}: {e}")
99
+ conn.rollback()
100
+ continue
101
+
102
+ conn.commit()
103
+ cur.close()
104
+ conn.close()
105
+ print(f"Stored {stored} papers.")
106
+
107
+
108
+ def run_ingestion(max_per_term: int = 500):
109
+ total = 0
110
+ for term in SEARCH_TERMS:
111
+ print(f"Fetching: {term}")
112
+ pmids = fetch_pubmed_ids(term, max_per_term)
113
+ print(f" Found {len(pmids)} papers")
114
+ papers = fetch_abstracts(pmids)
115
+ print(f" Fetched {len(papers)} abstracts")
116
+ store_papers(papers)
117
+ total += len(papers)
118
+ time.sleep(1) # be polite to NCBI API
119
+
120
+ print(f"\nIngestion complete. Total papers processed: {total}")
121
+
122
+
123
+ if __name__ == "__main__":
124
+ run_ingestion()