|
import gradio as gr |
|
import pandas as pd |
|
import numpy as np |
|
import os |
|
import base64 |
|
from together import Together |
|
|
|
def extract_medicines(api_key, image): |
|
""" |
|
Extract medicine names from a prescription image using Together AI's Llama-Vision-Free model |
|
""" |
|
# Check if API key is provided |
|
if not api_key: |
|
return "Please enter your Together API key." |
|
|
|
if image is None: |
|
return "Please upload an image." |
|
|
|
try: |
|
# Initialize Together client with the provided API key |
|
client = Together(api_key=api_key) |
|
|
|
# Convert image to base64 |
|
with open(image, "rb") as img_file: |
|
img_data = img_file.read() |
|
b64_img = base64.b64encode(img_data).decode('utf-8') |
|
|
|
# Make API call with base64 encoded image |
|
response = client.chat.completions.create( |
|
model="meta-llama/Llama-Vision-Free", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": "You are an expert in identifying medicine names from prescription images." |
|
}, |
|
{ |
|
"role": "user", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": "Please extract the names of the medicines only." |
|
}, |
|
{ |
|
"type": "image_url", |
|
"image_url": { |
|
"url": f"data:image/jpeg;base64,{b64_img}" |
|
} |
|
} |
|
] |
|
} |
|
] |
|
) |
|
|
|
# Extract medicine names from response |
|
medicine_list = response.choices[0].message.content |
|
return medicine_list |
|
|
|
except Exception as e: |
|
return f"Error: {str(e)}" |
|
|
|
def recommend_medicine(api_key, medicine_name, csv_file=None): |
|
""" |
|
Use Together API to recommend alternative medicines based on input medicine name |
|
using data from the provided CSV file with specific column structure. |
|
It will use AI to find similar medicines even if the exact name isn't in the dataset. |
|
""" |
|
try: |
|
# If CSV file is provided, use it; otherwise use default |
|
if csv_file is not None: |
|
# Read the uploaded CSV |
|
if isinstance(csv_file, str): # Path to default CSV |
|
df = pd.read_csv(csv_file) |
|
else: # Uploaded file |
|
df = pd.read_csv(csv_file.name) |
|
else: |
|
# Use the default medicine_dataset.csv in the current directory |
|
try: |
|
df = pd.read_csv("medicine_dataset.csv") |
|
except FileNotFoundError: |
|
return "Error: Default medicine_dataset.csv not found. Please upload a CSV file." |
|
|
|
# Check if medicine is in the dataset |
|
medicine_exists = medicine_name in df['name'].values |
|
|
|
# Create a helpful context about the dataset to send to the LLM |
|
dataset_overview = f"The dataset contains {len(df)} medicines with columns for name, substitutes, side effects, uses, chemical class, etc." |
|
|
|
# Sample of medicine names to give the model context |
|
sample_names = df['name'].sample(min(20, len(df))).tolist() |
|
medicine_sample = f"Sample medicines in the dataset: {', '.join(sample_names)}" |
|
|
|
# Extract specific medicine data if available |
|
medicine_data = None |
|
medicine_info_str = "" |
|
if medicine_exists: |
|
medicine_data = df[df['name'] == medicine_name] |
|
medicine_info_str = medicine_data.to_string(index=False) |
|
|
|
# Create system prompt with dataset context |
|
system_prompt = f"""You are a pharmaceutical expert system that recommends alternative medicines based on a comprehensive medicine dataset. The user has provided the medicine name "{medicine_name}". |
|
DATASET INFORMATION: |
|
{dataset_overview} |
|
{medicine_sample} |
|
The dataset has the following columns: |
|
- name: Medicine name |
|
- substitute0 through substitute4: Potential substitute medicines |
|
- sideEffect0 through sideEffect41: Possible side effects |
|
- use0 through use4: Medical uses |
|
- Chemical Class: The chemical classification |
|
- Habit Forming: Whether the medicine is habit-forming |
|
- Therapeutic Class: The therapeutic classification |
|
- Action Class: How the medicine works |
|
YOUR TASK: |
|
{"The medicine was found in the dataset with the following information:" if medicine_exists else "The medicine was NOT found in the dataset with an exact match. Your task is to:"} |
|
{medicine_info_str if medicine_exists else "1. Identify what kind of medicine this likely is based on its name (e.g., antibiotics, pain relievers, etc.)"} |
|
{'' if medicine_exists else "2. Look for medicines in the sample list that might be similar or serve similar purposes"} |
|
Please recommend alternative medicines for "{medicine_name}" with the following details for each: |
|
1. Name of the alternative medicine |
|
2. Why it's a good alternative (similar chemical composition, therapeutic use, etc.) |
|
3. Potential side effects to be aware of |
|
4. Usage recommendations |
|
5. Similarity to the original medicine (high, medium, low) |
|
Include at least 3-5 alternatives if possible. |
|
IMPORTANT: |
|
- If the medicine name contains strength or formulation (like "500mg" or "Duo"), focus on finding the base medicine first |
|
- Explain why these alternatives might be suitable replacements |
|
- Include appropriate medical disclaimers |
|
- Format your response clearly with headings for each alternative medicine |
|
""" |
|
|
|
# Initialize Together client with the API key |
|
client = Together(api_key=api_key) |
|
|
|
# Make API call |
|
response = client.chat.completions.create( |
|
model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": system_prompt |
|
}, |
|
{ |
|
"role": "user", |
|
"content": f"Please recommend alternatives for {medicine_name} based on the available information." |
|
} |
|
], |
|
max_tokens=2000, |
|
temperature=0.7 # Slightly higher temperature for creative recommendations |
|
) |
|
|
|
# Get the raw response |
|
recommendation_text = response.choices[0].message.content |
|
|
|
# Add disclaimer |
|
final_response = recommendation_text + "\n\n---\n\n**DISCLAIMER:** This information is for educational purposes only. Always consult with a healthcare professional before making any changes to your medication." |
|
|
|
return final_response |
|
|
|
except Exception as e: |
|
return f"Error: {str(e)}" |
|
|
|
def send_medicine_to_recommender(api_key, medicine_names, csv_file): |
|
""" |
|
Takes medicine names extracted from prescription and gets recommendations |
|
""" |
|
if not medicine_names or medicine_names.startswith("Error") or medicine_names.startswith("Please"): |
|
return "Please extract valid medicine names first" |
|
|
|
# Extract the first medicine name from the list (assuming it's the first line or first item) |
|
medicine_lines = medicine_names.strip().split('\n') |
|
if not medicine_lines: |
|
return "No valid medicine name found in extraction results" |
|
|
|
# Get the first medicine name (remove any bullet points or numbers) |
|
first_medicine = medicine_lines[0] |
|
# Clean up the medicine name (remove bullets, numbers, etc.) |
|
first_medicine = first_medicine.lstrip('•-*0123456789. ').strip() |
|
|
|
# Check if we have a valid medicine name |
|
if not first_medicine: |
|
return "Could not identify a valid medicine name from extraction" |
|
|
|
# Call the recommend medicine function with the first extracted medicine |
|
return recommend_medicine(api_key, first_medicine, csv_file) |
|
|
|
def analyze_full_prescription(api_key, medicine_names, csv_file): |
|
""" |
|
Takes all extracted medicine names and analyzes their interactions and provides comprehensive information |
|
""" |
|
if not medicine_names or medicine_names.startswith("Error") or medicine_names.startswith("Please"): |
|
return "Please extract valid medicine names first" |
|
|
|
try: |
|
# Parse the medicine names from the extracted text |
|
medicine_lines = medicine_names.strip().split('\n') |
|
cleaned_medicines = [] |
|
|
|
# Clean up medicine names (remove bullets, numbers, etc.) |
|
for medicine in medicine_lines: |
|
cleaned_medicine = medicine.lstrip('•-*0123456789. ').strip() |
|
if cleaned_medicine: |
|
cleaned_medicines.append(cleaned_medicine) |
|
|
|
if not cleaned_medicines: |
|
return "No valid medicine names found in extraction" |
|
|
|
# Create a prompt for the LLM to analyze the full prescription |
|
medicines_list = ", ".join(cleaned_medicines) |
|
|
|
system_prompt = f"""You are a pharmaceutical expert analyzing a full prescription containing the following medicines: {medicines_list}. |
|
Please provide a comprehensive analysis including: |
|
1. Purpose: The likely medical condition(s) being treated with this combination of medicines |
|
2. Potential interactions: Any known drug interactions between these medicines |
|
3. Side effects: Common side effects to watch for when taking this combination |
|
4. Recommendations: General advice for the patient taking these medicines |
|
5. Questions for the doctor: Important questions the patient should ask their healthcare provider |
|
Base your analysis on pharmacological knowledge about these medicines and their typical uses. |
|
""" |
|
|
|
# Initialize Together client with the API key |
|
client = Together(api_key=api_key) |
|
|
|
# Make API call |
|
response = client.chat.completions.create( |
|
model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": system_prompt |
|
}, |
|
{ |
|
"role": "user", |
|
"content": f"Please analyze this prescription with the following medicines: {medicines_list}" |
|
} |
|
], |
|
max_tokens=2000, |
|
temperature=0.3 # Lower temperature for more factual responses |
|
) |
|
|
|
analysis_text = response.choices[0].message.content |
|
|
|
# Add disclaimer |
|
final_response = analysis_text + "\n\n---\n\n**DISCLAIMER:** This analysis is for informational purposes only and should not replace professional medical advice. Always consult with your healthcare provider about your prescription." |
|
|
|
return final_response |
|
|
|
except Exception as e: |
|
return f"Error: {str(e)}" |
|
|
|
# Create Gradio interface with tabs for all functionalities |
|
with gr.Blocks(title="Medicine Assistant") as app: |
|
gr.Markdown("# Medicine Assistant") |
|
gr.Markdown("This application helps you extract medicine names from prescriptions, find alternative medicines, and analyze full prescriptions.") |
|
|
|
# API key input (shared between tabs) |
|
api_key_input = gr.Textbox( |
|
label="Together API Key", |
|
placeholder="Enter your Together API key here...", |
|
type="password" |
|
) |
|
|
|
# Create a file input for CSV that can be shared between tabs |
|
csv_file_input = gr.File( |
|
label="Upload Medicine CSV (Optional)", |
|
file_types=[".csv"], |
|
type="filepath" |
|
) |
|
gr.Markdown("If no CSV is uploaded, the app will use the default 'medicine_dataset.csv' file.") |
|
|
|
with gr.Tabs(): |
|
with gr.Tab("Prescription Medicine Extractor"): |
|
gr.Markdown("## Prescription Medicine Extractor") |
|
gr.Markdown("Upload a prescription image to extract medicine names using Together AI's Llama-Vision-Free model.") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
image_input = gr.Image(type="filepath", label="Upload Prescription Image") |
|
extract_btn = gr.Button("Extract Medicines") |
|
|
|
with gr.Column(): |
|
extracted_output = gr.Textbox(label="Extracted Medicines", lines=10) |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
recommend_from_extract_btn = gr.Button("Get Recommendations for First Medicine", variant="primary") |
|
analyze_full_btn = gr.Button("Analyze Full Prescription", variant="secondary") |
|
|
|
with gr.Column(scale=2): |
|
output_tabs = gr.Tabs() |
|
with output_tabs: |
|
with gr.Tab("Recommendations"): |
|
recommendation_from_extract_output = gr.Markdown() |
|
with gr.Tab("Full Analysis"): |
|
full_analysis_output = gr.Markdown() |
|
|
|
# Connect the buttons to functions |
|
extract_btn.click( |
|
fn=extract_medicines, |
|
inputs=[api_key_input, image_input], |
|
outputs=extracted_output |
|
) |
|
|
|
recommend_from_extract_btn.click( |
|
fn=send_medicine_to_recommender, |
|
inputs=[api_key_input, extracted_output, csv_file_input], |
|
outputs=recommendation_from_extract_output |
|
) |
|
|
|
analyze_full_btn.click( |
|
fn=analyze_full_prescription, |
|
inputs=[api_key_input, extracted_output, csv_file_input], |
|
outputs=full_analysis_output |
|
) |
|
|
|
gr.Markdown(""" |
|
### How to use: |
|
1. Enter your Together API key |
|
2. Upload a clear image of a prescription |
|
3. Click 'Extract Medicines' to see the identified medicines |
|
4. Optionally upload a custom medicine dataset CSV |
|
5. Choose to: |
|
- Get alternatives for the first medicine |
|
- Analyze the entire prescription for interactions and information |
|
|
|
### Note: |
|
- Your API key is used only for the current session |
|
- For best results, ensure the prescription image is clear and readable |
|
""") |
|
|
|
with gr.Tab("Medicine Alternative Recommender"): |
|
gr.Markdown("## Medicine Alternative Recommender") |
|
gr.Markdown("This tool recommends alternative medicines based on an input medicine name using the Together API.") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
medicine_name = gr.Textbox( |
|
label="Medicine Name", |
|
placeholder="Enter a medicine name (e.g., Augmentin 625 Duo)" |
|
) |
|
submit_btn = gr.Button("Get Recommendations", variant="primary") |
|
|
|
with gr.Column(): |
|
recommendation_output = gr.Markdown() |
|
|
|
submit_btn.click( |
|
recommend_medicine, |
|
inputs=[api_key_input, medicine_name, csv_file_input], |
|
outputs=recommendation_output |
|
) |
|
|
|
gr.Markdown(""" |
|
## How to use this tool: |
|
1. Enter your Together API key (same key used across the application) |
|
2. Enter a medicine name - the AI will find it or match similar alternatives |
|
3. Click "Get Recommendations" to see alternatives |
|
|
|
### Features: |
|
- Even if the exact medicine isn't in the database, the AI will try to find similar alternatives |
|
- The system analyzes the medicine name to determine its likely purpose and composition |
|
- Recommendations include substitutes, side effects, and usage information |
|
""") |
|
|
|
gr.Markdown(""" |
|
## About This Application |
|
|
|
This Medicine Assistant application combines powerful tools powered by Large Language Models: |
|
|
|
1. **Prescription Medicine Extractor**: Uses computer vision AI to identify medicine names from prescription images |
|
2. **Medicine Alternative Recommender**: Provides detailed information about alternative medications |
|
3. **Prescription Analyzer**: Analyzes entire prescriptions for potential interactions and insights |
|
|
|
All tools utilize the Together AI platform for advanced AI capabilities. Your API key is not stored and is only used to make API calls during your active session. |
|
|
|
### Important Note |
|
|
|
This application is for informational purposes only. Always consult with a healthcare professional before making any changes to your medication regimen. |
|
""") |
|
|
|
# Launch the app |
|
if __name__ == "__main__": |
|
app.launch() |