File size: 6,231 Bytes
1b899cb
 
 
f5128b8
1b899cb
 
366a700
f5128b8
 
 
1b899cb
f5128b8
 
 
 
 
 
 
 
 
 
 
 
 
1b899cb
 
 
 
 
 
f5128b8
 
1b899cb
 
 
 
f5128b8
1b899cb
 
 
 
 
f5128b8
1b899cb
 
 
 
 
f5128b8
1b899cb
 
 
 
f5128b8
1b899cb
f5128b8
 
1b899cb
 
ebbd1aa
 
4087716
ebbd1aa
1b899cb
 
 
f5128b8
4087716
1b899cb
f5128b8
1b899cb
 
 
 
 
 
 
 
 
 
 
4087716
 
 
 
1b899cb
4087716
 
 
 
1b899cb
 
 
 
f5128b8
1b899cb
 
4087716
 
f5128b8
1b899cb
f5128b8
68e917e
1b899cb
f5128b8
4087716
 
1b899cb
f5128b8
 
4087716
f5128b8
 
1b899cb
 
 
4087716
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b899cb
4087716
1b899cb
 
4087716
1b899cb
 
4087716
1b899cb
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import gradio as gr
from Bio import Entrez
from transformers import pipeline
import os  # For environment variables and file paths

# ---------------------------- Configuration ----------------------------
ENTREZ_EMAIL = os.environ.get("ENTREZ_EMAIL", "[email protected]")  # Use environment variable, default fallback
HUGGINGFACE_API_TOKEN = os.environ.get("HUGGINGFACE_API_TOKEN", "HUGGINGFACE_API_TOKEN") # Use environment variable, default fallback
SUMMARIZATION_MODEL = "facebook/bart-large-cnn"

# ---------------------------- Global Variables ----------------------------
summarizer = None
initialization_status = "Initializing..."  # Track initialization state

# ---------------------------- Helper Functions ----------------------------

def log_error(message: str):
    """Logs an error message to the console and a file (if possible)."""
    print(f"ERROR: {message}")
    try:
        with open("error_log.txt", "a") as f:
            f.write(f"{message}\n")
    except:
        print("Couldn't write to error log file.")  #If logging fails, still print to console

# ---------------------------- Tool Functions ----------------------------

def search_pubmed(query: str) -> list:
    """Searches PubMed and returns a list of article IDs."""
    try:
        Entrez.email = ENTREZ_EMAIL
        handle = Entrez.esearch(db="pubmed", term=query, retmax="5")
        record = Entrez.read(handle)
        handle.close()
        return record["IdList"]
    except Exception as e:
        log_error(f"PubMed search error: {e}")
        return [f"Error during PubMed search: {e}"]

def fetch_abstract(article_id: str) -> str:
    """Fetches the abstract for a given PubMed article ID."""
    try:
        Entrez.email = ENTREZ_EMAIL
        handle = Entrez.efetch(db="pubmed", id=article_id, rettype="abstract", retmode="text")
        abstract = handle.read()
        handle.close()
        return abstract
    except Exception as e:
        log_error(f"Error fetching abstract for {article_id}: {e}")
        return f"Error fetching abstract for {article_id}: {e}"

def summarize_abstract(abstract: str) -> str:
    """Summarizes an abstract using a transformer model."""
    global summarizer
    if summarizer is None:
        log_error("Summarizer not initialized.")
        return "Summarizer not initialized. Check initialization status."

    try:
        # Check if the abstract is empty or too short
        if not abstract or len(abstract.strip()) < 50:
            return "Abstract too short to summarize. A more detailed abstract was not found."

        summary = summarizer(abstract, max_length=130, min_length=30, do_sample=False)[0]['summary_text']
        return summary
    except Exception as e:
        log_error(f"Summarization error: {e}")
        return f"Error during summarization: Failed to generate concise summary with the current model."

# ---------------------------- Agent Function ----------------------------

def medai_agent(query: str) -> str:
    """Orchestrates the medical literature review and summarization."""
    article_ids = search_pubmed(query)

    if isinstance(article_ids, list) and article_ids:
        results = []
        for article_id in article_ids:
            abstract = fetch_abstract(article_id)
            if "Error" not in abstract:
                summary = summarize_abstract(abstract)
                results.append(f"<div class='article'>\n"
                               f"  <h3 class='article-id'>Article ID: {article_id}</h3>\n"
                               f"  <p class='summary'><strong>Summary:</strong> {summary}</p>\n"
                               f"</div>\n")
            else:
                results.append(f"<div class='article error'>\n"
                               f"  <h3 class='article-id'>Article ID: {article_id}</h3>\n"
                               f"  <p class='error-message'>Error processing article: {abstract}</p>\n"
                               f"</div>\n")
        return "\n".join(results)
    else:
        return f"No articles found or error occurred: {article_ids}"

# ---------------------------- Initialization and Setup ----------------------------

def setup():
    """Initializes the summarization model."""
    global summarizer, initialization_status
    initialization_status = "Initializing..."
    try:
        print("Initializing summarization pipeline...")
        initialization_status += "\nInitializing summarization pipeline..."
        summarizer = pipeline("summarization", model=SUMMARIZATION_MODEL, token=HUGGINGFACE_API_TOKEN)
        print("Summarization pipeline initialized.")
        initialization_status += f"\nSummarization pipeline initialized. Model {SUMMARIZATION_MODEL} loaded and ready."
        return initialization_status
    except Exception as e:
        initialization_status = f"Initialization error: {e}"
        log_error(initialization_status)
        return initialization_status

# ---------------------------- Gradio Interface ----------------------------

def launch_gradio():
    """Launches the Gradio interface."""
    global initialization_status

    # CSS to style the article output
    css = """
    .article {
      border: 1px solid #ddd;
      margin-bottom: 10px;
      padding: 10px;
      border-radius: 5px;
    }
    .article.error {
      border-color: #f00;
    }
    .article-id {
      font-size: 1.2em;
      margin-bottom: 5px;
    }
    .summary {
      font-style: italic;
    }
    .error-message {
      color: #f00;
    }
    """

    with gr.Blocks(css=css) as iface:
        gr.Markdown("# MedAI: Medical Literature Review and Summarization")
        status_display = gr.Textbox(value=initialization_status, interactive=False)
        query_input = gr.Textbox(lines=3, placeholder="Enter your medical query (e.g., 'new treatments for diabetes')...")
        submit_button = gr.Button("Submit")
        output_results = gr.HTML()  # Use HTML for formatted output

        submit_button.click(medai_agent, inputs=query_input, outputs=output_results)
        status_display.value = setup()

    iface.launch()

# ---------------------------- Main Execution ----------------------------

if __name__ == "__main__":
    launch_gradio()