Update app.py
Browse files
app.py
CHANGED
@@ -12,7 +12,7 @@ import plotly.graph_objects as go
|
|
12 |
from transformers import pipeline
|
13 |
import numpy as np
|
14 |
|
15 |
-
class
|
16 |
def __init__(self):
|
17 |
# Initialize NLP pipelines
|
18 |
try:
|
@@ -23,24 +23,54 @@ class CancerResearchLiteratureMiner:
|
|
23 |
self.summarizer = None
|
24 |
self.classifier = None
|
25 |
|
26 |
-
#
|
27 |
-
self.
|
28 |
-
"
|
29 |
-
"
|
30 |
-
"
|
|
|
|
|
31 |
]
|
32 |
|
33 |
-
# Animal
|
34 |
-
self.
|
35 |
-
"
|
36 |
-
"
|
37 |
-
"
|
|
|
|
|
|
|
38 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
-
def
|
41 |
-
"""Search PubMed for
|
42 |
-
# Enhance query with
|
43 |
-
enhanced_query = f"({query}) AND (
|
44 |
|
45 |
# Search PubMed
|
46 |
search_url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
|
@@ -123,19 +153,33 @@ class CancerResearchLiteratureMiner:
|
|
123 |
|
124 |
return papers
|
125 |
|
126 |
-
def
|
127 |
-
"""Analyze the retrieved papers for insights"""
|
128 |
if not papers or papers[0].get("error"):
|
129 |
return {"error": "No papers to analyze"}
|
130 |
|
131 |
analysis = {
|
132 |
"total_papers": len(papers),
|
133 |
"year_distribution": {},
|
134 |
-
"
|
135 |
-
"
|
136 |
-
"
|
|
|
137 |
"drug_mentions": [],
|
138 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
}
|
140 |
|
141 |
# Analyze each paper
|
@@ -144,42 +188,71 @@ class CancerResearchLiteratureMiner:
|
|
144 |
year = paper.get("year", "Unknown")
|
145 |
analysis["year_distribution"][year] = analysis["year_distribution"].get(year, 0) + 1
|
146 |
|
147 |
-
#
|
|
|
|
|
|
|
|
|
148 |
abstract = paper.get("abstract", "").lower()
|
149 |
title = paper.get("title", "").lower()
|
150 |
full_text = f"{title} {abstract}"
|
151 |
|
152 |
-
# Animal
|
153 |
-
for
|
154 |
-
if
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
-
# Extract drug mentions (simple regex for common drug patterns)
|
158 |
-
drugs = re.findall(r'\b[A-Z][a-z]*(?:mab|nib|ine|ole|cin|tin)\b', paper.get("abstract", ""))
|
159 |
analysis["drug_mentions"].extend(drugs)
|
160 |
|
161 |
# Classify research category if classifier is available
|
162 |
if self.classifier and abstract != "n/a":
|
163 |
try:
|
164 |
-
result = self.classifier(abstract[:512], self.
|
165 |
top_category = result["labels"][0]
|
166 |
-
analysis["
|
167 |
except Exception:
|
168 |
pass
|
169 |
|
170 |
# Process drug mentions
|
171 |
drug_counter = Counter(analysis["drug_mentions"])
|
172 |
-
analysis["drug_mentions"] = dict(drug_counter.most_common(
|
173 |
|
174 |
return analysis
|
175 |
|
176 |
-
def
|
177 |
-
"""Generate a comprehensive summary of findings"""
|
178 |
if not papers or papers[0].get("error"):
|
179 |
return "No papers found or error in retrieval."
|
180 |
|
181 |
summary = f"""
|
182 |
-
# Literature Mining Summary
|
183 |
|
184 |
## Overview
|
185 |
- **Total Papers Found**: {analysis['total_papers']}
|
@@ -187,108 +260,143 @@ class CancerResearchLiteratureMiner:
|
|
187 |
|
188 |
## Key Insights
|
189 |
|
190 |
-
### Animal
|
191 |
"""
|
192 |
|
193 |
-
# Top animal
|
194 |
-
if analysis["
|
195 |
-
|
196 |
-
for
|
197 |
-
|
|
|
198 |
|
199 |
-
summary += "\n###
|
200 |
|
201 |
-
#
|
202 |
-
if analysis["
|
203 |
-
|
204 |
-
for
|
205 |
-
|
|
|
206 |
|
207 |
-
summary += "\n###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
|
209 |
# Drug mentions
|
210 |
if analysis["drug_mentions"]:
|
211 |
-
for drug, count in list(analysis["drug_mentions"].items())[:
|
212 |
summary += f"- **{drug}**: {count} mentions\n"
|
213 |
|
214 |
-
summary += "\n###
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
|
216 |
-
|
|
|
|
|
217 |
current_year = datetime.now().year
|
218 |
-
recent_papers = [p for p in papers if p.get("year", "").isdigit() and int(p["year"]) >= current_year -
|
219 |
|
220 |
-
for paper in recent_papers[:
|
221 |
summary += f"- **{paper.get('title', 'N/A')}** ({paper.get('year', 'N/A')})\n"
|
222 |
summary += f" *{paper.get('journal', 'N/A')}*\n\n"
|
223 |
|
224 |
return summary
|
225 |
|
226 |
-
def
|
227 |
-
"""Create visualization plots"""
|
228 |
plots = {}
|
229 |
|
230 |
# Year distribution
|
231 |
if analysis["year_distribution"]:
|
232 |
-
years =
|
233 |
-
counts =
|
234 |
|
235 |
-
fig_year = px.
|
236 |
x=years, y=counts,
|
237 |
-
title="
|
238 |
-
labels={"x": "Year", "y": "Number of Papers"}
|
|
|
239 |
)
|
|
|
240 |
plots["year_dist"] = fig_year
|
241 |
|
242 |
-
# Animal
|
243 |
-
if analysis["
|
244 |
-
|
245 |
-
|
|
|
246 |
|
247 |
-
|
248 |
-
x=
|
249 |
orientation='h',
|
250 |
-
title="Most
|
251 |
-
labels={"x": "Number of Papers", "y": "
|
252 |
)
|
253 |
-
plots["
|
254 |
|
255 |
-
#
|
256 |
-
if analysis["
|
257 |
-
|
258 |
-
|
|
|
259 |
|
260 |
-
|
261 |
-
values=
|
262 |
-
title="
|
263 |
)
|
264 |
-
plots["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
|
266 |
return plots
|
267 |
|
268 |
-
def
|
269 |
-
"""Create the Gradio interface"""
|
270 |
-
miner =
|
271 |
|
272 |
-
def
|
273 |
-
"""Main function to search and analyze literature"""
|
274 |
if not query.strip():
|
275 |
-
return "Please enter a search query.", None, None, None, None
|
276 |
|
277 |
# Search papers
|
278 |
-
papers = miner.
|
279 |
|
280 |
if not papers or papers[0].get("error"):
|
281 |
error_msg = papers[0].get("error", "No papers found") if papers else "No papers found"
|
282 |
-
return f"Error: {error_msg}", None, None, None, None
|
283 |
|
284 |
# Analyze papers
|
285 |
-
analysis = miner.
|
286 |
|
287 |
# Generate summary
|
288 |
-
summary = miner.
|
289 |
|
290 |
# Create visualizations
|
291 |
-
plots = miner.
|
292 |
|
293 |
# Create papers dataframe
|
294 |
papers_df = pd.DataFrame([
|
@@ -306,98 +414,120 @@ def create_gradio_interface():
|
|
306 |
summary,
|
307 |
papers_df,
|
308 |
plots.get("year_dist"),
|
309 |
-
plots.get("
|
310 |
-
plots.get("
|
|
|
311 |
)
|
312 |
|
313 |
# Create interface
|
314 |
-
with gr.Blocks(title="Veterinary
|
315 |
gr.Markdown("""
|
316 |
-
# Veterinary
|
317 |
|
318 |
-
This AI agent searches and analyzes
|
319 |
-
It automatically extracts insights about animal
|
320 |
|
321 |
**Features:**
|
322 |
-
-
|
323 |
-
-
|
324 |
-
-
|
325 |
-
-
|
326 |
- Interactive visualizations
|
|
|
327 |
""")
|
328 |
|
329 |
with gr.Row():
|
330 |
with gr.Column(scale=2):
|
331 |
query_input = gr.Textbox(
|
332 |
label="Research Query",
|
333 |
-
placeholder="e.g., '
|
334 |
lines=2
|
335 |
)
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
341 |
|
342 |
with gr.Column(scale=1):
|
343 |
gr.Markdown("""
|
344 |
-
### Tips
|
345 |
-
-
|
346 |
-
-
|
347 |
-
-
|
|
|
|
|
348 |
""")
|
349 |
|
350 |
with gr.Tabs():
|
351 |
-
with gr.TabItem("
|
352 |
-
summary_output = gr.Markdown(label="Analysis
|
353 |
|
354 |
-
with gr.TabItem("Papers
|
355 |
papers_output = gr.Dataframe(
|
356 |
headers=["PMID", "Title", "Authors", "Journal", "Year"],
|
357 |
-
label="Retrieved Papers"
|
358 |
)
|
359 |
|
360 |
-
with gr.TabItem("
|
361 |
with gr.Row():
|
362 |
year_plot = gr.Plot(label="Publication Timeline")
|
363 |
-
|
364 |
with gr.Row():
|
365 |
-
|
|
|
366 |
|
367 |
# Connect the search function
|
368 |
search_btn.click(
|
369 |
-
|
370 |
-
inputs=[query_input, max_results],
|
371 |
-
outputs=[summary_output, papers_output, year_plot,
|
372 |
)
|
373 |
|
374 |
# Add examples
|
375 |
gr.Examples(
|
376 |
examples=[
|
377 |
-
["
|
378 |
-
["
|
379 |
-
["
|
380 |
-
["
|
|
|
|
|
|
|
|
|
381 |
],
|
382 |
-
inputs=[query_input, max_results]
|
383 |
)
|
384 |
|
385 |
gr.Markdown("""
|
386 |
-
### About This Agent
|
387 |
-
|
388 |
-
|
389 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
390 |
|
391 |
-
**Data Sources:** PubMed/NCBI databases
|
392 |
**Last Updated:** June 2025
|
393 |
-
**
|
394 |
""")
|
395 |
|
396 |
return interface
|
397 |
|
398 |
# Create and launch the interface
|
399 |
if __name__ == "__main__":
|
400 |
-
interface =
|
401 |
interface.launch(
|
402 |
server_name="0.0.0.0",
|
403 |
server_port=7860,
|
|
|
12 |
from transformers import pipeline
|
13 |
import numpy as np
|
14 |
|
15 |
+
class VeterinaryLiteratureMiner:
|
16 |
def __init__(self):
|
17 |
# Initialize NLP pipelines
|
18 |
try:
|
|
|
23 |
self.summarizer = None
|
24 |
self.classifier = None
|
25 |
|
26 |
+
# Veterinary research categories for classification
|
27 |
+
self.veterinary_categories = [
|
28 |
+
"oncology", "cardiology", "dermatology", "neurology", "orthopedics",
|
29 |
+
"infectious diseases", "parasitology", "pharmacology", "toxicology",
|
30 |
+
"surgery", "anesthesia", "emergency medicine", "internal medicine",
|
31 |
+
"pathology", "radiology", "nutrition", "behavior", "reproduction",
|
32 |
+
"public health", "zoonoses", "immunology", "genetics", "epidemiology"
|
33 |
]
|
34 |
|
35 |
+
# Animal species categories
|
36 |
+
self.animal_species = [
|
37 |
+
"canine", "dog", "dogs", "feline", "cat", "cats", "equine", "horse", "horses",
|
38 |
+
"bovine", "cattle", "cow", "cows", "porcine", "pig", "pigs", "swine",
|
39 |
+
"ovine", "sheep", "caprine", "goat", "goats", "avian", "bird", "birds",
|
40 |
+
"poultry", "chicken", "chickens", "rabbit", "rabbits", "ferret", "ferrets",
|
41 |
+
"reptile", "reptiles", "fish", "aquatic", "wildlife", "zoo", "exotic",
|
42 |
+
"laboratory animals", "mouse", "mice", "rat", "rats"
|
43 |
]
|
44 |
+
|
45 |
+
# Veterinary specialties and procedures
|
46 |
+
self.vet_procedures = [
|
47 |
+
"vaccination", "spay", "neuter", "castration", "ovariohysterectomy",
|
48 |
+
"amputation", "biopsy", "endoscopy", "laparoscopy", "arthroscopy",
|
49 |
+
"radiography", "ultrasound", "CT", "MRI", "chemotherapy", "radiation",
|
50 |
+
"physical therapy", "rehabilitation", "dental", "ophthalmology"
|
51 |
+
]
|
52 |
+
|
53 |
+
# Common veterinary conditions
|
54 |
+
self.vet_conditions = [
|
55 |
+
"diabetes", "epilepsy", "heart disease", "kidney disease", "liver disease",
|
56 |
+
"arthritis", "hip dysplasia", "allergies", "skin disease", "cancer",
|
57 |
+
"tumor", "infection", "parasite", "heartworm", "flea", "tick",
|
58 |
+
"obesity", "dental disease", "cataracts", "glaucoma", "IBD"
|
59 |
+
]
|
60 |
+
|
61 |
+
def search_veterinary_literature(self, query: str, max_results: int = 50, database: str = "pubmed") -> List[Dict]:
|
62 |
+
"""Search veterinary literature across multiple databases"""
|
63 |
+
|
64 |
+
if database == "pubmed":
|
65 |
+
return self._search_pubmed(query, max_results)
|
66 |
+
else:
|
67 |
+
# Future: Could add other veterinary databases here
|
68 |
+
return self._search_pubmed(query, max_results)
|
69 |
|
70 |
+
def _search_pubmed(self, query: str, max_results: int) -> List[Dict]:
|
71 |
+
"""Search PubMed for veterinary papers"""
|
72 |
+
# Enhance query with veterinary terms
|
73 |
+
enhanced_query = f"({query}) AND (veterinary OR animal OR pet OR livestock OR zoo OR wildlife)"
|
74 |
|
75 |
# Search PubMed
|
76 |
search_url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
|
|
|
153 |
|
154 |
return papers
|
155 |
|
156 |
+
def analyze_veterinary_papers(self, papers: List[Dict]) -> Dict:
|
157 |
+
"""Analyze the retrieved veterinary papers for insights"""
|
158 |
if not papers or papers[0].get("error"):
|
159 |
return {"error": "No papers to analyze"}
|
160 |
|
161 |
analysis = {
|
162 |
"total_papers": len(papers),
|
163 |
"year_distribution": {},
|
164 |
+
"animal_species": {},
|
165 |
+
"veterinary_specialties": {},
|
166 |
+
"common_conditions": {},
|
167 |
+
"procedures_mentioned": {},
|
168 |
"drug_mentions": [],
|
169 |
+
"journal_distribution": {},
|
170 |
+
"research_trends": {}
|
171 |
+
}
|
172 |
+
|
173 |
+
# Keywords for different categories
|
174 |
+
specialty_keywords = {
|
175 |
+
"oncology": ["cancer", "tumor", "oncology", "chemotherapy", "radiation"],
|
176 |
+
"cardiology": ["heart", "cardiac", "cardiology", "arrhythmia", "murmur"],
|
177 |
+
"dermatology": ["skin", "dermatology", "allergy", "dermatitis", "eczema"],
|
178 |
+
"neurology": ["brain", "neurological", "seizure", "epilepsy", "paralysis"],
|
179 |
+
"orthopedics": ["bone", "joint", "fracture", "orthopedic", "lameness"],
|
180 |
+
"infectious_diseases": ["infection", "bacteria", "virus", "antibiotic", "pathogen"],
|
181 |
+
"surgery": ["surgical", "surgery", "operative", "laparoscopy", "endoscopy"],
|
182 |
+
"internal_medicine": ["diabetes", "kidney", "liver", "endocrine", "metabolic"]
|
183 |
}
|
184 |
|
185 |
# Analyze each paper
|
|
|
188 |
year = paper.get("year", "Unknown")
|
189 |
analysis["year_distribution"][year] = analysis["year_distribution"].get(year, 0) + 1
|
190 |
|
191 |
+
# Journal distribution
|
192 |
+
journal = paper.get("journal", "Unknown")
|
193 |
+
analysis["journal_distribution"][journal] = analysis["journal_distribution"].get(journal, 0) + 1
|
194 |
+
|
195 |
+
# Analyze abstract and title
|
196 |
abstract = paper.get("abstract", "").lower()
|
197 |
title = paper.get("title", "").lower()
|
198 |
full_text = f"{title} {abstract}"
|
199 |
|
200 |
+
# Animal species detection
|
201 |
+
for species in self.animal_species:
|
202 |
+
if species in full_text:
|
203 |
+
species_key = species.replace(" ", "_")
|
204 |
+
analysis["animal_species"][species_key] = analysis["animal_species"].get(species_key, 0) + 1
|
205 |
+
|
206 |
+
# Veterinary specialty detection
|
207 |
+
for specialty, keywords in specialty_keywords.items():
|
208 |
+
for keyword in keywords:
|
209 |
+
if keyword in full_text:
|
210 |
+
analysis["veterinary_specialties"][specialty] = analysis["veterinary_specialties"].get(specialty, 0) + 1
|
211 |
+
break
|
212 |
+
|
213 |
+
# Common conditions detection
|
214 |
+
for condition in self.vet_conditions:
|
215 |
+
if condition in full_text:
|
216 |
+
analysis["common_conditions"][condition] = analysis["common_conditions"].get(condition, 0) + 1
|
217 |
+
|
218 |
+
# Procedures detection
|
219 |
+
for procedure in self.vet_procedures:
|
220 |
+
if procedure in full_text:
|
221 |
+
analysis["procedures_mentioned"][procedure] = analysis["procedures_mentioned"].get(procedure, 0) + 1
|
222 |
+
|
223 |
+
# Extract drug mentions (veterinary drugs and general pharmaceuticals)
|
224 |
+
drugs = re.findall(r'\b[A-Z][a-z]*(?:mab|nib|ine|ole|cin|tin|zole|pril|sartan)\b', paper.get("abstract", ""))
|
225 |
+
# Add common veterinary drugs
|
226 |
+
vet_drugs = ["prednisolone", "dexamethasone", "amoxicillin", "cephalexin", "enrofloxacin",
|
227 |
+
"tramadol", "gabapentin", "furosemide", "enalapril", "pimobendan"]
|
228 |
+
for drug in vet_drugs:
|
229 |
+
if drug in full_text:
|
230 |
+
drugs.append(drug.title())
|
231 |
|
|
|
|
|
232 |
analysis["drug_mentions"].extend(drugs)
|
233 |
|
234 |
# Classify research category if classifier is available
|
235 |
if self.classifier and abstract != "n/a":
|
236 |
try:
|
237 |
+
result = self.classifier(abstract[:512], self.veterinary_categories)
|
238 |
top_category = result["labels"][0]
|
239 |
+
analysis["research_trends"][top_category] = analysis["research_trends"].get(top_category, 0) + 1
|
240 |
except Exception:
|
241 |
pass
|
242 |
|
243 |
# Process drug mentions
|
244 |
drug_counter = Counter(analysis["drug_mentions"])
|
245 |
+
analysis["drug_mentions"] = dict(drug_counter.most_common(15))
|
246 |
|
247 |
return analysis
|
248 |
|
249 |
+
def generate_veterinary_summary(self, papers: List[Dict], analysis: Dict) -> str:
|
250 |
+
"""Generate a comprehensive summary of veterinary literature findings"""
|
251 |
if not papers or papers[0].get("error"):
|
252 |
return "No papers found or error in retrieval."
|
253 |
|
254 |
summary = f"""
|
255 |
+
# Veterinary Literature Mining Summary
|
256 |
|
257 |
## Overview
|
258 |
- **Total Papers Found**: {analysis['total_papers']}
|
|
|
260 |
|
261 |
## Key Insights
|
262 |
|
263 |
+
### Most Studied Animal Species
|
264 |
"""
|
265 |
|
266 |
+
# Top animal species
|
267 |
+
if analysis["animal_species"]:
|
268 |
+
top_species = sorted(analysis["animal_species"].items(), key=lambda x: x[1], reverse=True)[:8]
|
269 |
+
for species, count in top_species:
|
270 |
+
formatted_species = species.replace("_", " ").title()
|
271 |
+
summary += f"- **{formatted_species}**: {count} papers\n"
|
272 |
|
273 |
+
summary += "\n### Veterinary Specialties Focus\n"
|
274 |
|
275 |
+
# Veterinary specialties
|
276 |
+
if analysis["veterinary_specialties"]:
|
277 |
+
top_specialties = sorted(analysis["veterinary_specialties"].items(), key=lambda x: x[1], reverse=True)[:6]
|
278 |
+
for specialty, count in top_specialties:
|
279 |
+
formatted_specialty = specialty.replace("_", " ").title()
|
280 |
+
summary += f"- **{formatted_specialty}**: {count} papers\n"
|
281 |
|
282 |
+
summary += "\n### Common Conditions Studied\n"
|
283 |
+
|
284 |
+
# Common conditions
|
285 |
+
if analysis["common_conditions"]:
|
286 |
+
top_conditions = sorted(analysis["common_conditions"].items(), key=lambda x: x[1], reverse=True)[:8]
|
287 |
+
for condition, count in top_conditions:
|
288 |
+
summary += f"- **{condition.title()}**: {count} papers\n"
|
289 |
+
|
290 |
+
summary += "\n### Frequently Mentioned Treatments/Drugs\n"
|
291 |
|
292 |
# Drug mentions
|
293 |
if analysis["drug_mentions"]:
|
294 |
+
for drug, count in list(analysis["drug_mentions"].items())[:8]:
|
295 |
summary += f"- **{drug}**: {count} mentions\n"
|
296 |
|
297 |
+
summary += "\n### Top Veterinary Journals\n"
|
298 |
+
|
299 |
+
# Journal distribution
|
300 |
+
if analysis["journal_distribution"]:
|
301 |
+
top_journals = sorted(analysis["journal_distribution"].items(), key=lambda x: x[1], reverse=True)[:5]
|
302 |
+
for journal, count in top_journals:
|
303 |
+
summary += f"- **{journal}**: {count} papers\n"
|
304 |
|
305 |
+
summary += "\n### Recent Research Highlights\n"
|
306 |
+
|
307 |
+
# Recent papers (last 3 years)
|
308 |
current_year = datetime.now().year
|
309 |
+
recent_papers = [p for p in papers if p.get("year", "").isdigit() and int(p["year"]) >= current_year - 3]
|
310 |
|
311 |
+
for paper in recent_papers[:4]:
|
312 |
summary += f"- **{paper.get('title', 'N/A')}** ({paper.get('year', 'N/A')})\n"
|
313 |
summary += f" *{paper.get('journal', 'N/A')}*\n\n"
|
314 |
|
315 |
return summary
|
316 |
|
317 |
+
def create_veterinary_visualizations(self, analysis: Dict):
|
318 |
+
"""Create visualization plots for veterinary data"""
|
319 |
plots = {}
|
320 |
|
321 |
# Year distribution
|
322 |
if analysis["year_distribution"]:
|
323 |
+
years = [y for y in analysis["year_distribution"].keys() if y.isdigit()]
|
324 |
+
counts = [analysis["year_distribution"][y] for y in years]
|
325 |
|
326 |
+
fig_year = px.line(
|
327 |
x=years, y=counts,
|
328 |
+
title="Veterinary Research Publications Over Time",
|
329 |
+
labels={"x": "Year", "y": "Number of Papers"},
|
330 |
+
markers=True
|
331 |
)
|
332 |
+
fig_year.update_layout(showlegend=False)
|
333 |
plots["year_dist"] = fig_year
|
334 |
|
335 |
+
# Animal species
|
336 |
+
if analysis["animal_species"]:
|
337 |
+
species = list(analysis["animal_species"].keys())[:12]
|
338 |
+
species_counts = [analysis["animal_species"][s] for s in species]
|
339 |
+
formatted_species = [s.replace("_", " ").title() for s in species]
|
340 |
|
341 |
+
fig_species = px.bar(
|
342 |
+
x=species_counts, y=formatted_species,
|
343 |
orientation='h',
|
344 |
+
title="Most Studied Animal Species",
|
345 |
+
labels={"x": "Number of Papers", "y": "Species"}
|
346 |
)
|
347 |
+
plots["animal_species"] = fig_species
|
348 |
|
349 |
+
# Veterinary specialties
|
350 |
+
if analysis["veterinary_specialties"]:
|
351 |
+
specialties = list(analysis["veterinary_specialties"].keys())
|
352 |
+
spec_counts = list(analysis["veterinary_specialties"].values())
|
353 |
+
formatted_specialties = [s.replace("_", " ").title() for s in specialties]
|
354 |
|
355 |
+
fig_specialties = px.pie(
|
356 |
+
values=spec_counts, names=formatted_specialties,
|
357 |
+
title="Veterinary Specialty Distribution"
|
358 |
)
|
359 |
+
plots["specialties"] = fig_specialties
|
360 |
+
|
361 |
+
# Common conditions
|
362 |
+
if analysis["common_conditions"]:
|
363 |
+
conditions = list(analysis["common_conditions"].keys())[:10]
|
364 |
+
condition_counts = [analysis["common_conditions"][c] for c in conditions]
|
365 |
+
|
366 |
+
fig_conditions = px.bar(
|
367 |
+
x=[c.title() for c in conditions], y=condition_counts,
|
368 |
+
title="Most Commonly Studied Conditions",
|
369 |
+
labels={"x": "Condition", "y": "Number of Papers"}
|
370 |
+
)
|
371 |
+
fig_conditions.update_xaxes(tickangle=45)
|
372 |
+
plots["conditions"] = fig_conditions
|
373 |
|
374 |
return plots
|
375 |
|
376 |
+
def create_veterinary_gradio_interface():
|
377 |
+
"""Create the Gradio interface for veterinary literature mining"""
|
378 |
+
miner = VeterinaryLiteratureMiner()
|
379 |
|
380 |
+
def search_and_analyze_vet(query, max_results, database):
|
381 |
+
"""Main function to search and analyze veterinary literature"""
|
382 |
if not query.strip():
|
383 |
+
return "Please enter a search query.", None, None, None, None, None
|
384 |
|
385 |
# Search papers
|
386 |
+
papers = miner.search_veterinary_literature(query, max_results, database)
|
387 |
|
388 |
if not papers or papers[0].get("error"):
|
389 |
error_msg = papers[0].get("error", "No papers found") if papers else "No papers found"
|
390 |
+
return f"Error: {error_msg}", None, None, None, None, None
|
391 |
|
392 |
# Analyze papers
|
393 |
+
analysis = miner.analyze_veterinary_papers(papers)
|
394 |
|
395 |
# Generate summary
|
396 |
+
summary = miner.generate_veterinary_summary(papers, analysis)
|
397 |
|
398 |
# Create visualizations
|
399 |
+
plots = miner.create_veterinary_visualizations(analysis)
|
400 |
|
401 |
# Create papers dataframe
|
402 |
papers_df = pd.DataFrame([
|
|
|
414 |
summary,
|
415 |
papers_df,
|
416 |
plots.get("year_dist"),
|
417 |
+
plots.get("animal_species"),
|
418 |
+
plots.get("specialties"),
|
419 |
+
plots.get("conditions")
|
420 |
)
|
421 |
|
422 |
# Create interface
|
423 |
+
with gr.Blocks(title="Veterinary Literature Mining Agent", theme=gr.themes.Soft()) as interface:
|
424 |
gr.Markdown("""
|
425 |
+
# πΎ Veterinary Literature Mining Agent
|
426 |
|
427 |
+
This AI agent searches and analyzes veterinary and animal health literature across all specialties.
|
428 |
+
It automatically extracts insights about animal species, veterinary specialties, common conditions, and treatment trends.
|
429 |
|
430 |
**Features:**
|
431 |
+
- Comprehensive veterinary literature search
|
432 |
+
- Multi-species analysis (companion animals, livestock, wildlife, exotics)
|
433 |
+
- Veterinary specialty categorization
|
434 |
+
- Treatment and drug trend analysis
|
435 |
- Interactive visualizations
|
436 |
+
- Journal and publication pattern analysis
|
437 |
""")
|
438 |
|
439 |
with gr.Row():
|
440 |
with gr.Column(scale=2):
|
441 |
query_input = gr.Textbox(
|
442 |
label="Research Query",
|
443 |
+
placeholder="e.g., 'canine diabetes management', 'equine lameness diagnosis', 'feline kidney disease', 'wildlife conservation medicine'",
|
444 |
lines=2
|
445 |
)
|
446 |
+
with gr.Row():
|
447 |
+
max_results = gr.Slider(
|
448 |
+
minimum=10, maximum=100, value=50, step=10,
|
449 |
+
label="Maximum Results"
|
450 |
+
)
|
451 |
+
database_choice = gr.Dropdown(
|
452 |
+
choices=["pubmed"],
|
453 |
+
value="pubmed",
|
454 |
+
label="Database"
|
455 |
+
)
|
456 |
+
search_btn = gr.Button("π Search Veterinary Literature", variant="primary")
|
457 |
|
458 |
with gr.Column(scale=1):
|
459 |
gr.Markdown("""
|
460 |
+
### Search Tips:
|
461 |
+
- **Species**: dog, cat, horse, cattle, pig, bird, fish, reptile, wildlife
|
462 |
+
- **Specialties**: cardiology, oncology, surgery, dermatology, neurology
|
463 |
+
- **Conditions**: diabetes, arthritis, cancer, infection, allergies
|
464 |
+
- **Procedures**: vaccination, surgery, imaging, therapy
|
465 |
+
- **Combine terms**: "feline diabetes insulin therapy"
|
466 |
""")
|
467 |
|
468 |
with gr.Tabs():
|
469 |
+
with gr.TabItem("π Analysis Summary"):
|
470 |
+
summary_output = gr.Markdown(label="Veterinary Literature Analysis")
|
471 |
|
472 |
+
with gr.TabItem("π Research Papers"):
|
473 |
papers_output = gr.Dataframe(
|
474 |
headers=["PMID", "Title", "Authors", "Journal", "Year"],
|
475 |
+
label="Retrieved Veterinary Papers"
|
476 |
)
|
477 |
|
478 |
+
with gr.TabItem("π Research Trends"):
|
479 |
with gr.Row():
|
480 |
year_plot = gr.Plot(label="Publication Timeline")
|
481 |
+
species_plot = gr.Plot(label="Animal Species")
|
482 |
with gr.Row():
|
483 |
+
specialties_plot = gr.Plot(label="Veterinary Specialties")
|
484 |
+
conditions_plot = gr.Plot(label="Common Conditions")
|
485 |
|
486 |
# Connect the search function
|
487 |
search_btn.click(
|
488 |
+
search_and_analyze_vet,
|
489 |
+
inputs=[query_input, max_results, database_choice],
|
490 |
+
outputs=[summary_output, papers_output, year_plot, species_plot, specialties_plot, conditions_plot]
|
491 |
)
|
492 |
|
493 |
# Add examples
|
494 |
gr.Examples(
|
495 |
examples=[
|
496 |
+
["canine diabetes insulin therapy", 40, "pubmed"],
|
497 |
+
["equine lameness diagnosis imaging", 35, "pubmed"],
|
498 |
+
["feline chronic kidney disease treatment", 45, "pubmed"],
|
499 |
+
["bovine mastitis antibiotic resistance", 30, "pubmed"],
|
500 |
+
["avian influenza surveillance wild birds", 35, "pubmed"],
|
501 |
+
["exotic animal anesthesia protocols", 25, "pubmed"],
|
502 |
+
["wildlife conservation medicine", 40, "pubmed"],
|
503 |
+
["small animal oncology chemotherapy", 50, "pubmed"]
|
504 |
],
|
505 |
+
inputs=[query_input, max_results, database_choice]
|
506 |
)
|
507 |
|
508 |
gr.Markdown("""
|
509 |
+
### About This Veterinary Literature Mining Agent
|
510 |
+
|
511 |
+
This comprehensive tool is designed for veterinary professionals, researchers, and students to efficiently
|
512 |
+
search and analyze veterinary literature across all animal species and medical specialties.
|
513 |
+
|
514 |
+
**Supported Areas:**
|
515 |
+
- **Companion Animals**: Dogs, cats, rabbits, ferrets, birds, reptiles, fish
|
516 |
+
- **Large Animals**: Horses, cattle, pigs, sheep, goats
|
517 |
+
- **Wildlife & Zoo Medicine**: All wild species and conservation medicine
|
518 |
+
- **Laboratory Animals**: Research and laboratory animal medicine
|
519 |
+
- **All Veterinary Specialties**: Internal medicine, surgery, oncology, cardiology, dermatology, etc.
|
520 |
|
521 |
+
**Data Sources:** PubMed/NCBI databases with veterinary focus
|
522 |
**Last Updated:** June 2025
|
523 |
+
**Coverage:** All aspects of veterinary medicine and animal health
|
524 |
""")
|
525 |
|
526 |
return interface
|
527 |
|
528 |
# Create and launch the interface
|
529 |
if __name__ == "__main__":
|
530 |
+
interface = create_veterinary_gradio_interface()
|
531 |
interface.launch(
|
532 |
server_name="0.0.0.0",
|
533 |
server_port=7860,
|