File size: 7,317 Bytes
7014076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import gradio as gr
import time
from collections import defaultdict
import spacy

# Load the symptom-to-disease mapping
symptom_data = {
    "Shortness of breath": {
        "questions": [
            "Do you also have chest pain?",
            "Do you feel fatigued often?",
            "Have you noticed swelling in your legs?"
        ],
        "diseases": ["Atelectasis", "Emphysema", "Edema"],
        "weights_yes": [30, 30, 40],
        "weights_no": [10, 20, 30]
    },
    "Persistent cough": {
        "questions": [
            "Is your cough dry or with mucus?",
            "Do you experience fever?",
            "Do you have difficulty breathing?"
        ],
        "diseases": ["Pneumonia", "Fibrosis", "Infiltration"],
        "weights_yes": [35, 30, 35],
        "weights_no": [10, 15, 20]
    },
    "Sharp chest pain": {
        "questions": [
            "Does it worsen with deep breaths?",
            "Do you feel lightheaded?",
            "Have you had recent trauma or surgery?"
        ],
        "diseases": ["Pneumothorax", "Effusion", "Cardiomegaly"],
        "weights_yes": [40, 30, 30],
        "weights_no": [15, 20, 25]
    },
    "Fatigue & swelling": {
        "questions": [
            "Do you feel breathless when lying down?",
            "Have you gained weight suddenly?",
            "Do you experience irregular heartbeat?"
        ],
        "diseases": ["Edema", "Cardiomegaly"],
        "weights_yes": [50, 30, 20],
        "weights_no": [20, 15, 15]
    },
    "Chronic wheezing": {
        "questions": [
            "Do you have a history of smoking?",
            "Do you feel tightness in your chest?",
            "Do you have frequent lung infections?"
        ],
        "diseases": ["Emphysema", "Fibrosis"],
        "weights_yes": [40, 30, 30],
        "weights_no": [15, 25, 20]
    }
}

# Load spaCy model for NLP
nlp = spacy.load("en_core_web_lg")

# Function to extract key symptom from user input
def extract_symptom(user_input):
    # Define the symptoms that the chatbot recognizes
    known_symptoms = list(symptom_data.keys())
    
    # Process the input with spaCy NLP model
    user_doc = nlp(user_input.lower())
    
    # Check if any of the known symptoms are in the user input
    for symptom in known_symptoms:
        if symptom.lower() in user_input.lower():
            return symptom
    
    # If no direct match, use similarity to find the closest symptom
    similarities = {}
    for symptom in known_symptoms:
        symptom_doc = nlp(symptom.lower())
        similarity = user_doc.similarity(symptom_doc)
        similarities[symptom] = similarity
    
    # Return the symptom with the highest similarity
    return max(similarities, key=similarities.get)

# Mapping of unrecognized symptoms to similar known ones
synonym_mapping = {
    "chest pain": "Sharp chest pain",
    "pain in chest": "Sharp chest pain",
    "wheezing": "Chronic wheezing",
    "cough": "Persistent cough",
    "shortness of breath": "Shortness of breath",
    "fatigue": "Fatigue & swelling"
}

# Global variables to track user state
user_state = {}

def chatbot(user_input):
    if "state" not in user_state:
        user_state["state"] = "greet"
    
    if user_state["state"] == "greet":
        user_state["state"] = "ask_symptom"
        return "Hello! I'm a medical AI assistant. Please describe your primary symptom."
    
    elif user_state["state"] == "ask_symptom":
        # Check if the symptom contains any synonym or keyword
        matched_symptom = None
        
        for synonym, recognized_symptom in synonym_mapping.items():
            if synonym in user_input.lower():
                matched_symptom = recognized_symptom
                break
        
        # If no synonym found, extract the symptom using NLP
        if not matched_symptom:
            matched_symptom = extract_symptom(user_input)
        
        # If the symptom is recognized, proceed to the next step
        if matched_symptom not in symptom_data:
            user_state["state"] = "ask_feeling"
            return "I'm sorry, I don't recognize that symptom. How do you feel?"
        
        user_state["symptom"] = matched_symptom
        user_state["state"] = "ask_duration"
        return "How long have you been experiencing this symptom? (Less than a week / More than a week)"
    
    elif user_state["state"] == "ask_feeling":
        # If the symptom is not recognized, ask how they feel
        return "Can you describe your symptoms in more detail?"
    
    elif user_state["state"] == "ask_duration":
        if user_input.lower() == "less than a week":
            user_state.clear()
            return "It might be a temporary issue. Please monitor your symptoms and consult a doctor if they persist."
        elif user_input.lower() == "more than a week":
            user_state["state"] = "follow_up"
            user_state["current_question"] = 0
            user_state["disease_scores"] = defaultdict(int)
            return symptom_data[user_state["symptom"]]["questions"][0]
        else:
            return "Please respond with 'Less than a week' or 'More than a week'."
    
    elif user_state["state"] == "follow_up":
        symptom = user_state["symptom"]
        question_index = user_state["current_question"]
        
        # Update probabilities
        if user_input.lower() == "yes":
            for i, disease in enumerate(symptom_data[symptom]["diseases"]):
                user_state["disease_scores"][disease] += symptom_data[symptom]["weights_yes"][i]
        else:
            for i, disease in enumerate(symptom_data[symptom]["diseases"]):
                user_state["disease_scores"][disease] += symptom_data[symptom]["weights_no"][i]
        
        # Move to the next question or finish
        user_state["current_question"] += 1
        if user_state["current_question"] < len(symptom_data[symptom]["questions"]):
            return symptom_data[symptom]["questions"][user_state["current_question"]]
        
        # Final diagnosis
        probable_disease = max(user_state["disease_scores"], key=user_state["disease_scores"].get)
        user_state.clear()
        return f"Based on your symptoms, the most likely condition is: {probable_disease}. Please consult a doctor for confirmation."

# Gradio Chatbot UI with improved features
with gr.Blocks() as demo:
    gr.Markdown("# Conversational Image Recognition Assistant: AI-Powered X-ray Diagnosis for Healthcare")
    chatbot_ui = gr.Chatbot()
    user_input = gr.Textbox(placeholder="Enter your response...", label="Your Message")
    submit = gr.Button("Send")
    clear_chat = gr.Button("Clear Chat")
    
    def respond(user_message, history):
        history.append((user_message, "Thinking..."))  # Show thinking message
        yield history, ""  # Immediate update
        
        time.sleep(1.5)  # Simulate processing delay
        bot_response = chatbot(user_message)
        history[-1] = (user_message, bot_response)  # Update with real response
        yield history, ""
    
    submit.click(respond, [user_input, chatbot_ui], [chatbot_ui, user_input])
    user_input.submit(respond, [user_input, chatbot_ui], [chatbot_ui, user_input])
    clear_chat.click(lambda: ([], ""), outputs=[chatbot_ui, user_input])

demo.launch()