mgbam commited on
Commit
3987ef0
·
verified ·
1 Parent(s): 978c4cf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -110
app.py CHANGED
@@ -1,119 +1,69 @@
1
- import os
2
- from fastapi import FastAPI, Query, HTTPException
3
- from typing import List, Dict, Optional
4
- import httpx
5
- import openai
6
-
7
- # ENVIRONMENT VARIABLES for API keys (set these securely in your deployment)
8
- ARXIV_API = "http://export.arxiv.org/api/query?search_query="
9
- PUBMED_API = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
10
- PUBMED_FETCH = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi"
11
- OPENFDA_ENDPOINT = "https://api.fda.gov/drug/event.json"
12
- UMLS_AUTH = "https://utslogin.nlm.nih.gov/cas/v1/api-key"
13
- UMLS_SEARCH = "https://uts-ws.nlm.nih.gov/rest/search/current"
14
- OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
15
- UMLS_API_KEY = os.environ.get("UMLS_KEY")
16
- PUB_KEY = os.environ.get("PUB_KEY")
17
-
18
- app = FastAPI(
19
- title="Ultimate AI-Powered Research MCP Server",
20
- description="Integrates ArXiv, PubMed, OpenFDA, UMLS, and OpenAI for world-class research.",
21
- version="1.0.0",
22
- )
23
 
24
- # -- Utility Functions --
25
-
26
- async def fetch_arxiv(query: str) -> List[Dict]:
27
- # Use httpx or requests to fetch arXiv results
28
- # Parse and return relevant metadata (simplified for brevity)
29
- url = f"{ARXIV_API}{query}&max_results=5"
30
- async with httpx.AsyncClient() as client:
31
- r = await client.get(url)
32
- # TODO: Parse arXiv Atom XML and extract paper metadata
33
- return []
34
 
35
- async def fetch_pubmed(query: str) -> List[Dict]:
36
- # Use PubMed e-utilities for search and fetch
37
- params = {"db": "pubmed", "term": query, "retmode": "json", "api_key": PUB_KEY, "retmax": 5}
38
- async with httpx.AsyncClient() as client:
39
- r = await client.get(PUBMED_API, params=params)
40
- ids = r.json()["esearchresult"]["idlist"]
41
- fetch_params = {"db": "pubmed", "id": ",".join(ids), "retmode": "xml", "api_key": PUB_KEY}
42
- rf = await client.get(PUBMED_FETCH, params=fetch_params)
43
- # TODO: Parse PubMed XML to get metadata
44
- return []
45
 
46
- async def fetch_umls(term: str) -> Dict:
47
- # Authenticate with UMLS and fetch CUIs for term
48
- async with httpx.AsyncClient() as client:
49
- auth = await client.post(UMLS_AUTH, data={"apikey": UMLS_API_KEY})
50
- ticket = auth.text # TODO: parse ticket
51
- params = {"string": term, "ticket": ticket}
52
- search = await client.get(UMLS_SEARCH, params=params)
53
- # TODO: Extract CUIs and definitions
54
- return {}
55
 
56
- async def fetch_openfda(drug: str) -> Dict:
57
- params = {"search": f"patient.drug.medicinalproduct:{drug}", "limit": 3}
58
- async with httpx.AsyncClient() as client:
59
- r = await client.get(OPENFDA_ENDPOINT, params=params)
60
- # TODO: Parse adverse event data
61
- return {}
62
 
63
- async def ai_summarize(text: str) -> str:
64
- openai.api_key = OPENAI_API_KEY
65
- response = openai.ChatCompletion.create(
66
- model="gpt-4o",
67
- messages=[
68
- {"role": "system", "content": "You are an expert biomedical research assistant."},
69
- {"role": "user", "content": f"Summarize and synthesize: {text}"}
70
- ],
71
- max_tokens=256
 
72
  )
73
- return response['choices'][0]['message']['content']
74
 
75
- # -- Endpoints --
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
- @app.post("/unified_search")
78
- async def unified_search(query: str):
79
- arxiv = await fetch_arxiv(query)
80
- pubmed = await fetch_pubmed(query)
81
- all_papers = arxiv + pubmed
82
- # TODO: Semantic ranking (e.g., use OpenAI embeddings for similarity)
83
- # Extract keywords for UMLS/Drug enrichment
84
- keywords = [] # TODO: implement keyword extraction (e.g., spaCy)
85
- umls_results = [await fetch_umls(k) for k in keywords]
86
- drug_data = [await fetch_openfda(k) for k in keywords]
87
- summary = await ai_summarize(str(all_papers))
88
- return {
89
- "papers": all_papers,
90
- "umls": umls_results,
91
- "drug_safety": drug_data,
92
- "ai_summary": summary,
93
- "suggested_reading": [p.get('link') for p in all_papers[:3]]
94
- }
95
-
96
- @app.get("/get_umls_info")
97
- async def get_umls_info(term: str):
98
- result = await fetch_umls(term)
99
- return result
100
-
101
- @app.get("/fetch_drug_safety")
102
- async def fetch_drug_safety(drug: str):
103
- result = await fetch_openfda(drug)
104
- return result
105
-
106
- @app.post("/ask_ai")
107
- async def ask_ai(question: str, context: Optional[str] = None):
108
- openai.api_key = OPENAI_API_KEY
109
- response = openai.ChatCompletion.create(
110
- model="gpt-4o",
111
- messages=[
112
- {"role": "system", "content": "You are an advanced multi-domain biomedical research agent. Use information from ArXiv, PubMed, OpenFDA, and UMLS when answering."},
113
- {"role": "user", "content": f"Question: {question}\nContext: {context or ''}"}
114
- ],
115
- max_tokens=512
116
- )
117
- return {"answer": response['choices'][0]['message']['content']}
118
 
119
- # -- Extensibility: Plug-and-play new tools via simple Python modules and endpoint registration. --
 
 
 
 
 
 
 
1
+ # app.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ import os
4
+ import streamlit as st
5
+ from fastapi import FastAPI
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from mcp.orchestrator import orchestrate_search, answer_ai_question
8
+ from mcp.schemas import UnifiedSearchInput, UnifiedSearchResult
 
 
 
 
9
 
10
+ # Initialize FastAPI app for API users
11
+ api = FastAPI(title="MCP Research Server", version="2.0")
12
+ api.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
 
 
 
 
 
 
 
13
 
14
+ @api.post("/unified_search", response_model=UnifiedSearchResult)
15
+ async def unified_search_endpoint(data: UnifiedSearchInput):
16
+ return await orchestrate_search(data.query)
 
 
 
 
 
 
17
 
18
+ @api.post("/ask_ai")
19
+ async def ask_ai_endpoint(question: str, context: str = ""):
20
+ return await answer_ai_question(question, context)
 
 
 
21
 
22
+ # Streamlit UI for Hugging Face Space
23
+ def render_ui():
24
+ st.set_page_config(page_title="Ultimate Research Assistant", page_icon=":microscope:", layout="wide")
25
+ st.image("assets/logo.png", width=100)
26
+ st.title("🔬 Next-Gen AI-Powered Biomedical Research Assistant")
27
+ st.markdown(
28
+ """
29
+ *Combine the power of ArXiv, PubMed, UMLS, OpenFDA, and OpenAI.
30
+ Get instant, unified, semantically-ranked answers—plus drug safety, concept enrichment, and expert Q&A!*
31
+ """
32
  )
 
33
 
34
+ query = st.text_input("Enter your research question or topic:", value="What are the latest treatments for Alzheimer's disease?")
35
+ if st.button("Run Unified Search 🚀"):
36
+ with st.spinner("Retrieving and synthesizing knowledge..."):
37
+ results = orchestrate_search(query)
38
+ st.success("Here are the results!")
39
+ for i, paper in enumerate(results['papers'], 1):
40
+ st.markdown(f"**{i}. [{paper['title']}]({paper['link']})** \n*{paper['authors']}*")
41
+ st.write(paper['summary'])
42
+ st.subheader("UMLS Concept Enrichment")
43
+ for c in results['umls']:
44
+ st.write(f"**{c['name']}** (CUI: {c['cui']}): {c['definition']}")
45
+ st.subheader("Drug & Safety Insights")
46
+ for d in results['drug_safety']:
47
+ st.write(d)
48
+ st.subheader("AI-Generated Synthesis")
49
+ st.info(results['ai_summary'])
50
+ st.markdown("#### 📚 Suggested Reading")
51
+ for link in results['suggested_reading']:
52
+ st.write(f"- {link}")
53
 
54
+ st.markdown("---")
55
+ st.subheader("🤖 Ask a follow-up (AI Q&A):")
56
+ follow_up = st.text_input("Type your question here:")
57
+ if st.button("Ask AI"):
58
+ with st.spinner("AI is thinking..."):
59
+ answer = answer_ai_question(follow_up, context=query)
60
+ st.success("AI says:")
61
+ st.write(answer['answer'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ if __name__ == "__main__":
64
+ import sys
65
+ if "runserver" in sys.argv:
66
+ import uvicorn
67
+ uvicorn.run(api, host="0.0.0.0", port=7860)
68
+ else:
69
+ render_ui()