Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -14,7 +14,7 @@ reasoning_ai_model = os.getenv("REASONING_AI_MODEL")
|
|
14 |
# Configure the OpenAI client with your custom API endpoint and API key.
|
15 |
client = OpenAI(base_url=openai_base_url, api_key=openai_api_key)
|
16 |
|
17 |
-
medical_recommendations = "MEDICAL RECOMMENDATIONS:\n\n" + "Birth control options sorted by effectiveness (typical-use rates), with brief pros, cons, and side effects:\n\nHighly Effective Methods (failure rate <1%)\n-Sterilization\n- Prevention rate: >99%\n- Pros: Permanent and low maintenance\n- Cons: Irreversible; requires surgery\n-
|
18 |
|
19 |
SYSTEM_PROMPT = "You are a medical professional. Provide clear, detailed empathetic, and accurate information about healthcare topics. **You must always use markdown and bullet points.** Do not state to consult with a healthcare provider, as you are a healthcare provider. Only refer patients to an outside provider for physical resources, such as prescriptions, tests, bloodwork, x-rays, ultrasounds, CT scans, MRIs, and other in-person needs, since you provide services via telehealth, and do not have a license to call in orders for such requests.\n\n" # + medical_recommendations
|
20 |
|
@@ -101,10 +101,10 @@ def apply_replacements(text):
|
|
101 |
text = text.replace(phrase, replacement)
|
102 |
return text
|
103 |
|
104 |
-
def chat_with_openai(message: str, history: list, temperature: float, max_new_tokens: int, fast_mode: bool = False
|
105 |
"""
|
106 |
Call the OpenAI ChatCompletion endpoint using the new client and yield streaming responses.
|
107 |
-
|
108 |
Implements <think> logic and retries if the full response is blank.
|
109 |
|
110 |
Args:
|
@@ -116,11 +116,7 @@ def chat_with_openai(message: str, history: list, temperature: float, max_new_to
|
|
116 |
Yields:
|
117 |
str: Partial cumulative output from the assistant.
|
118 |
"""
|
119 |
-
|
120 |
-
# If this is the first message after an import, use the imported history
|
121 |
-
if imported_history and not history:
|
122 |
-
history = imported_history.copy()
|
123 |
-
|
124 |
conversation = []
|
125 |
|
126 |
if (not history and message.startswith("Start a talk therapy session with me.")) or \
|
@@ -180,14 +176,14 @@ def chat_with_openai(message: str, history: list, temperature: float, max_new_to
|
|
180 |
safe_portion = pending_buffer[:-max_phrase_length] if len(pending_buffer) > max_phrase_length else ""
|
181 |
if safe_portion:
|
182 |
display_text += apply_replacements(safe_portion)
|
183 |
-
yield
|
184 |
pending_buffer = pending_buffer[-max_phrase_length:]
|
185 |
|
186 |
# Flush remaining text.
|
187 |
if pending_buffer:
|
188 |
safe_portion = pending_buffer
|
189 |
display_text += apply_replacements(safe_portion)
|
190 |
-
yield
|
191 |
|
192 |
# Check if the full response is valid.
|
193 |
if full_response.strip():
|
@@ -195,11 +191,11 @@ def chat_with_openai(message: str, history: list, temperature: float, max_new_to
|
|
195 |
|
196 |
# If no valid response was generated after 5 attempts
|
197 |
if not full_response.strip():
|
198 |
-
yield
|
199 |
else:
|
200 |
-
# Apply replacements and append modified response to history
|
201 |
modified_full_response = apply_replacements(full_response)
|
202 |
-
|
203 |
|
204 |
def export_chat(history):
|
205 |
"""Export chat history as a JSONL file in OpenAI messages format."""
|
@@ -247,13 +243,13 @@ def import_chat(file):
|
|
247 |
i = 1
|
248 |
|
249 |
while i < len(messages) - 1:
|
250 |
-
if messages[i]["role"] == "user" and messages[i
|
251 |
-
new_history.append((messages[i]["content"], messages[i
|
252 |
i += 2
|
253 |
else:
|
254 |
i += 1
|
255 |
-
|
256 |
-
return new_history #
|
257 |
except Exception as e:
|
258 |
raise gr.Error(f"Error importing chat: {str(e)}")
|
259 |
|
@@ -267,8 +263,6 @@ with gr.Blocks(css=css) as demo:
|
|
267 |
# Add the checkbox directly to the layout
|
268 |
fast_mode_checkbox = gr.Checkbox(label="Fast Mode (Skips Reasoning. Provides Immediate, Less Accurate Responses.) RECOMMENDED FOR TALK THERAPY.", value=False)
|
269 |
|
270 |
-
imported_history = gr.State([]) # State for imported history
|
271 |
-
|
272 |
chat_interface = gr.ChatInterface(
|
273 |
fn=chat_with_openai,
|
274 |
chatbot=chatbot,
|
@@ -278,7 +272,6 @@ with gr.Blocks(css=css) as demo:
|
|
278 |
gr.Slider(minimum=0.6, maximum=0.6, step=0.1, value=0.6, label="Temperature", render=False, visible=False),
|
279 |
gr.Slider(minimum=1024, maximum=4096, step=128, value=2048, label="Max new tokens", render=False, visible=False),
|
280 |
fast_mode_checkbox,
|
281 |
-
imported_history
|
282 |
],
|
283 |
examples=[
|
284 |
['What is PrEP, and how do I know if I need it?'],
|
@@ -296,9 +289,9 @@ with gr.Blocks(css=css) as demo:
|
|
296 |
|
297 |
# Connect buttons to functions
|
298 |
export_btn.click(fn=export_chat, inputs=chatbot, outputs=gr.File(label="Download Chat History"))
|
299 |
-
import_btn.upload(fn=import_chat, inputs=[import_btn], outputs=
|
300 |
|
301 |
gr.Markdown(LICENSE)
|
302 |
|
303 |
if __name__ == "__main__":
|
304 |
-
demo.launch(share=True)
|
|
|
14 |
# Configure the OpenAI client with your custom API endpoint and API key.
|
15 |
client = OpenAI(base_url=openai_base_url, api_key=openai_api_key)
|
16 |
|
17 |
+
medical_recommendations = "MEDICAL RECOMMENDATIONS:\n\n" + "Birth control options sorted by effectiveness (typical-use rates), with brief pros, cons, and side effects:\n\nHighly Effective Methods (failure rate <1%)\n-Sterilization\n- Prevention rate: >99%\n- Pros: Permanent and low maintenance\n- Cons: Irreversible; requires surgery\n- side effects: Surgical risks (infection, pain)\n\n-Intrauterine Devices (IUDs) – Hormonal and Copper\n- Prevention rate: >99%\n- Pros: Long-term (3–10 years), low maintenance, reversible\n- Cons: Requires provider insertion; possible initial discomfort\n- Side effects:\n - Hormonal IUD: Initial irregular bleeding\n - Copper IUD: Heavier periods, cramping; rare risk of expulsion or uterine perforation\n\n-Implant (e.g., Nexplanon)\n- Prevention rate: >99%\n- Pros: Lasts up to 3 years, low maintenance, reversible\n- Cons: Requires minor procedure for insertion and removal; may cause irregular bleeding\n- Side effects: Mood changes, headaches, weight gain, pain at insertion site\n\nModerately Effective Methods (failure rate ~1–9%)\n-Injectable (e.g., Depo-Provera)\n- Prevention rate: ~96%\n- Pros: Injection every 3 months; high efficacy when on schedule\n- Cons: Can cause irregular bleeding; fertility may be delayed after stopping\n- Side effects: Weight gain, mood swings, potential bone density loss, injection site reactions\n\n-Oral Contraceptive Pills (combined or progestin-only)\n- Prevention rate: ~91%\n- Pros: Regulates cycles, may reduce cramps and help with acne; quick return to fertility\n- Cons: Must be taken daily; effectiveness depends on correct use\n- Side effects: Risk of blood clots (especially for smokers or women over 35), nausea, breast tenderness, mood changes, possible increased blood pressure\n- Prescriptions: Yaz, Yasmin, Ortho TriCyclen, Alesse, Loestrin\n- OTC: OPill $20/month, Taken Daily\n\n-Transdermal Patch (e.g., Ortho Evra)\n- Prevention rate: ~91%\n- Pros: Weekly application; steady hormone delivery\n- Cons: May cause skin irritation; visible on skin; less effective if detached\n- Side effects: Similar to pills (blood clots, nausea, breast tenderness, headaches)\n\n-Vaginal Ring (e.g., NuvaRing)\n- Prevention rate: ~91%\n- Pros: Monthly insertion; lower systemic hormone levels\n- Cons: Requires comfort with insertion and removal; possible vaginal discomfort\n- Side effects: Risk of blood clots, mood changes, headaches, vaginal irritation\n\nLess Effective Methods (failure rate 10% or higher)\n-Barrier Methods\n- Male Condoms\n - Prevention rate: ~87%\n - Pros: Also protect against STIs; non-hormonal; widely available\n - Cons: Effectiveness depends on correct use; may break or slip\n - Side effects: Possible latex allergy\n- Female Condoms\n - Prevention rate: ~79%\n - Pros: Offer STI protection; female-controlled\n - Cons: More expensive; less available; may be harder to use\n - Side effects: Possible irritation or allergic reaction\n- Diaphragms and Cervical Caps\n - Prevention rate: ~83–88%\n - Pros: Reusable; non-hormonal\n - Cons: Must be used with spermicide; requires proper fitting and timing\n - Side effects: Potential irritation, allergic reactions, increased risk of UTIs\n\n-Spermicides (used alone)\n- Prevention rate: ~79%\n- Pros: Over-the-counter; can be combined with other methods\n- Cons: Lower effectiveness when used alone; requires application every time\n- Side effects: May cause irritation or allergic reactions\n\n-Fertility Awareness Methods\n- Prevention rate: ~76% (varies widely)\n- Pros: No hormones or devices; increases understanding of your cycle\n- Cons: Requires daily tracking and strict adherence; higher risk of unintended pregnancy if not followed precisely\n- Side effects: None medically\n\n-Withdrawal (Coitus Interruptus)\n- Prevention rate: ~78%\n- Pros: No cost; non-hormonal\n- Cons: Relies heavily on timing; risk from pre-ejaculate\n- Side effects: No direct side effects; may cause stress if it fails\n\nTreatments for Managing HIV:\n- **Integrase Strand Transfer Inhibitor (INSTI)–Based Regimens:** \n - Bictegravir/emtricitabine/tenofovir alafenamide (Biktarvy) \n - Dolutegravir/lamivudine/abacavir (Triumeq)\n\n- **Non-Nucleoside Reverse Transcriptase Inhibitor (NNRTI)–Based Regimen:** \n - Efavirenz/emtricitabine/tenofovir disoproxil fumarate (Atripla)\n\n- **Protease Inhibitor (PI)–Based Regimen:** \n - Darunavir (boosted with ritonavir or cobicistat) plus two NRTIs"
|
18 |
|
19 |
SYSTEM_PROMPT = "You are a medical professional. Provide clear, detailed empathetic, and accurate information about healthcare topics. **You must always use markdown and bullet points.** Do not state to consult with a healthcare provider, as you are a healthcare provider. Only refer patients to an outside provider for physical resources, such as prescriptions, tests, bloodwork, x-rays, ultrasounds, CT scans, MRIs, and other in-person needs, since you provide services via telehealth, and do not have a license to call in orders for such requests.\n\n" # + medical_recommendations
|
20 |
|
|
|
101 |
text = text.replace(phrase, replacement)
|
102 |
return text
|
103 |
|
104 |
+
def chat_with_openai(message: str, history: list, temperature: float, max_new_tokens: int, fast_mode: bool = False):
|
105 |
"""
|
106 |
Call the OpenAI ChatCompletion endpoint using the new client and yield streaming responses.
|
107 |
+
|
108 |
Implements <think> logic and retries if the full response is blank.
|
109 |
|
110 |
Args:
|
|
|
116 |
Yields:
|
117 |
str: Partial cumulative output from the assistant.
|
118 |
"""
|
119 |
+
|
|
|
|
|
|
|
|
|
120 |
conversation = []
|
121 |
|
122 |
if (not history and message.startswith("Start a talk therapy session with me.")) or \
|
|
|
176 |
safe_portion = pending_buffer[:-max_phrase_length] if len(pending_buffer) > max_phrase_length else ""
|
177 |
if safe_portion:
|
178 |
display_text += apply_replacements(safe_portion)
|
179 |
+
yield display_text
|
180 |
pending_buffer = pending_buffer[-max_phrase_length:]
|
181 |
|
182 |
# Flush remaining text.
|
183 |
if pending_buffer:
|
184 |
safe_portion = pending_buffer
|
185 |
display_text += apply_replacements(safe_portion)
|
186 |
+
yield display_text
|
187 |
|
188 |
# Check if the full response is valid.
|
189 |
if full_response.strip():
|
|
|
191 |
|
192 |
# If no valid response was generated after 5 attempts
|
193 |
if not full_response.strip():
|
194 |
+
yield "*The assistant did not provide a response. Please try again.*"
|
195 |
else:
|
196 |
+
# Apply replacements and append modified response to history.
|
197 |
modified_full_response = apply_replacements(full_response)
|
198 |
+
history.append((message, modified_full_response))
|
199 |
|
200 |
def export_chat(history):
|
201 |
"""Export chat history as a JSONL file in OpenAI messages format."""
|
|
|
243 |
i = 1
|
244 |
|
245 |
while i < len(messages) - 1:
|
246 |
+
if messages[i]["role"] == "user" and messages[i+1]["role"] == "assistant":
|
247 |
+
new_history.append((messages[i]["content"], messages[i+1]["content"]))
|
248 |
i += 2
|
249 |
else:
|
250 |
i += 1
|
251 |
+
|
252 |
+
return gr.update(value=new_history) # Update the chatbot state
|
253 |
except Exception as e:
|
254 |
raise gr.Error(f"Error importing chat: {str(e)}")
|
255 |
|
|
|
263 |
# Add the checkbox directly to the layout
|
264 |
fast_mode_checkbox = gr.Checkbox(label="Fast Mode (Skips Reasoning. Provides Immediate, Less Accurate Responses.) RECOMMENDED FOR TALK THERAPY.", value=False)
|
265 |
|
|
|
|
|
266 |
chat_interface = gr.ChatInterface(
|
267 |
fn=chat_with_openai,
|
268 |
chatbot=chatbot,
|
|
|
272 |
gr.Slider(minimum=0.6, maximum=0.6, step=0.1, value=0.6, label="Temperature", render=False, visible=False),
|
273 |
gr.Slider(minimum=1024, maximum=4096, step=128, value=2048, label="Max new tokens", render=False, visible=False),
|
274 |
fast_mode_checkbox,
|
|
|
275 |
],
|
276 |
examples=[
|
277 |
['What is PrEP, and how do I know if I need it?'],
|
|
|
289 |
|
290 |
# Connect buttons to functions
|
291 |
export_btn.click(fn=export_chat, inputs=chatbot, outputs=gr.File(label="Download Chat History"))
|
292 |
+
import_btn.upload(fn=import_chat, inputs=[import_btn], outputs=chatbot) # Fixed connection
|
293 |
|
294 |
gr.Markdown(LICENSE)
|
295 |
|
296 |
if __name__ == "__main__":
|
297 |
+
demo.launch(share=True)
|