ciaochris commited on
Commit
6d3e5ce
·
verified ·
1 Parent(s): 5012a88

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -1
app.py CHANGED
@@ -8,7 +8,159 @@ import plotly.graph_objs as go
8
  from typing import List, Dict, Any
9
  import logging
10
 
11
- # ... (previous code remains unchanged)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  def clear_inputs():
14
  return gr.Number(value=None), gr.Radio(value=None), gr.Textbox(value=""), gr.Textbox(value="")
 
8
  from typing import List, Dict, Any
9
  import logging
10
 
11
+ # Set up logging
12
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
13
+
14
+ # Load environment variables
15
+ load_dotenv()
16
+
17
+ # Initialize Groq client
18
+ client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
19
+
20
+ def parse_non_json_response(text: str) -> Dict[str, Any]:
21
+ # Attempt to extract structured information from non-JSON text
22
+ cancer_types = re.findall(r"(?:cancer type|Cancer Type):\s*(.+?)(?:\n|$)", text, re.IGNORECASE)
23
+ risk_levels = re.findall(r"(?:risk level|Risk Level):\s*(.+?)(?:\n|$)", text, re.IGNORECASE)
24
+ descriptions = re.findall(r"(?:description|Description):\s*(.+?)(?:\n|$)", text, re.IGNORECASE)
25
+
26
+ potential_cancer_types = [
27
+ {"name": ct, "risk_level": rl, "description": desc}
28
+ for ct, rl, desc in zip(cancer_types, risk_levels, descriptions)
29
+ ]
30
+
31
+ recommended_tests = re.findall(r"(?:Test Name):\s*(.+?)\n(?:description|Description):\s*(.+?)(?:\n|$)", text, re.IGNORECASE)
32
+ recommended_tests = [{"name": name, "description": desc} for name, desc in recommended_tests]
33
+
34
+ general_advice = re.search(r"(?:General Advice|general advice):\s*(.+?)(?:\n|$)", text, re.DOTALL | re.IGNORECASE)
35
+ general_advice = general_advice.group(1) if general_advice else "No general advice provided."
36
+
37
+ disclaimer = re.search(r"(?:DISCLAIMER|Disclaimer):\s*(.+?)(?:\n|$)", text, re.DOTALL | re.IGNORECASE)
38
+ disclaimer = disclaimer.group(1) if disclaimer else "No disclaimer provided. This tool is for educational purposes only and should not replace professional medical advice."
39
+
40
+ return {
41
+ "potential_cancer_types": potential_cancer_types,
42
+ "recommended_tests": recommended_tests,
43
+ "general_advice": general_advice,
44
+ "disclaimer": disclaimer
45
+ }
46
+
47
+ def get_diagnosis(age: int, gender: str, symptoms: str, medical_history: str) -> Dict[str, Any]:
48
+ prompt = f"""
49
+ Given the following patient information, provide a preliminary analysis of potential cancer risks and recommended tests.
50
+ Give professional medical advice to the best of your ability.
51
+
52
+ Patient Information:
53
+ Age: {age}
54
+ Gender: {gender}
55
+ Symptoms: {symptoms}
56
+ Medical History: {medical_history}
57
+
58
+ Please provide a response with the following structure:
59
+ Potential Cancer Types:
60
+ - Cancer Type: [Name]
61
+ Risk Level: [Low/Medium/High]
62
+ Description: [Brief description of why this cancer type is considered]
63
+ Recommended Tests:
64
+ - Test Name: [Name]
65
+ Description: [Brief description of why this test is recommended]
66
+ General Advice: [General health advice for the patient]
67
+ DISCLAIMER: [A strong disclaimer about the limitations of this assessment]
68
+
69
+ Ensure the response emphasizes the importance of consulting with a medical professional for accurate diagnosis and treatment.
70
+ """
71
+
72
+ try:
73
+ chat_completion = client.chat.completions.create(
74
+ messages=[
75
+ {
76
+ "role": "user",
77
+ "content": prompt,
78
+ }
79
+ ],
80
+ model="llama-3.1-8b-instant",
81
+ temperature=0.5,
82
+ max_tokens=1500,
83
+ )
84
+
85
+ response_content = chat_completion.choices[0].message.content
86
+
87
+ try:
88
+ response = json.loads(response_content)
89
+ except json.JSONDecodeError:
90
+ response = parse_non_json_response(response_content)
91
+
92
+ return response
93
+ except Exception as e:
94
+ logging.error(f"Error in get_diagnosis: {str(e)}")
95
+ return {"error": f"An error occurred while communicating with the API: {str(e)}"}
96
+
97
+ def plot_risk(potential_cancer_types: List[Dict[str, str]]) -> go.Figure:
98
+ if not potential_cancer_types:
99
+ return None
100
+
101
+ names = [c["name"] for c in potential_cancer_types]
102
+ risk_levels = [1 if c["risk_level"].lower() == "low" else 2 if c["risk_level"].lower() == "medium" else 3 for c in potential_cancer_types]
103
+ colors = ["green" if rl == 1 else "yellow" if rl == 2 else "red" for rl in risk_levels]
104
+
105
+ fig = go.Figure(data=[go.Bar(
106
+ x=names,
107
+ y=risk_levels,
108
+ marker_color=colors,
109
+ text=risk_levels,
110
+ textposition='auto',
111
+ )])
112
+ fig.update_layout(
113
+ title="Cancer Risk Levels",
114
+ yaxis_title="Risk Level",
115
+ xaxis_tickangle=-45,
116
+ yaxis=dict(
117
+ tickmode='array',
118
+ tickvals=[1, 2, 3],
119
+ ticktext=['Low', 'Medium', 'High']
120
+ )
121
+ )
122
+
123
+ return fig
124
+
125
+ def format_output(response: Dict[str, Any]) -> str:
126
+ if "error" in response:
127
+ return f"Error: {response['error']}"
128
+
129
+ output = "HealthScan AI: Personalized Cancer Risk Insights\n\n"
130
+
131
+ output += "Potential Cancer Types:\n"
132
+ for cancer in response.get("potential_cancer_types", []):
133
+ output += f"- {cancer.get('name', 'N/A')} (Risk Level: {cancer.get('risk_level', 'N/A')})\n"
134
+ output += f" {cancer.get('description', 'No description provided.')}\n\n"
135
+
136
+ output += "Recommended Tests:\n"
137
+ for test in response.get("recommended_tests", []):
138
+ output += f"- {test.get('name', 'N/A')}: {test.get('description', 'No description provided.')}\n\n"
139
+
140
+ output += f"General Advice:\n{response.get('general_advice', 'No general advice provided.')}\n\n"
141
+ output += f"DISCLAIMER:\n{response.get('disclaimer', 'No disclaimer provided. This tool is for educational purposes only and should not replace professional medical advice.')}"
142
+
143
+ return output
144
+
145
+ def validate_input(age: int, gender: str, symptoms: str, medical_history: str) -> List[str]:
146
+ errors = []
147
+ if not (0 < age < 120):
148
+ errors.append("Please enter a valid age between 1 and 120.")
149
+ if not symptoms.strip():
150
+ errors.append("Please enter at least one symptom.")
151
+ return errors
152
+
153
+ def process_input(age: int, gender: str, symptoms: str, medical_history: str) -> tuple:
154
+ errors = validate_input(age, gender, symptoms, medical_history)
155
+ if errors:
156
+ return "\n".join(errors), None
157
+
158
+ diagnosis = get_diagnosis(age, gender, symptoms, medical_history)
159
+ output = format_output(diagnosis)
160
+
161
+ risk_plot = plot_risk(diagnosis.get("potential_cancer_types", []))
162
+
163
+ return output, risk_plot
164
 
165
  def clear_inputs():
166
  return gr.Number(value=None), gr.Radio(value=None), gr.Textbox(value=""), gr.Textbox(value="")