Spaces:
Sleeping
Sleeping
| import anthropic | |
| from dotenv import load_dotenv | |
| import os | |
| from fasthtml.common import * | |
| from dataclasses import dataclass | |
| load_dotenv() | |
| # Shared styles | |
| SHARED_STYLES = """ | |
| @keyframes progress { | |
| 0% { width: 0%; } | |
| 50% { width: 70%; } | |
| 100% { width: 100%; } | |
| } | |
| .htmx-indicator { | |
| display: none; | |
| } | |
| .htmx-request .htmx-indicator { | |
| display: block; | |
| } | |
| .htmx-request.htmx-indicator { | |
| display: block; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 50px auto; | |
| padding: 20px; | |
| font-family: Arial, sans-serif; | |
| } | |
| .btn-primary { | |
| display: inline-block; | |
| padding: 10px 20px; | |
| background-color: #007bff; | |
| color: white; | |
| text-decoration: none; | |
| border-radius: 5px; | |
| border: none; | |
| cursor: pointer; | |
| } | |
| .content-box { | |
| white-space: pre-wrap; | |
| background-color: #f5f5f5; | |
| padding: 20px; | |
| border-radius: 5px; | |
| line-height: 1.6; | |
| } | |
| """ | |
| def create_loader(): | |
| """Create a reusable loading indicator""" | |
| return Div( | |
| id="loader", | |
| cls="htmx-indicator", | |
| style="margin-top: 20px;" | |
| )( | |
| Div("Loading drug information...", style="color: #007bff; font-weight: bold;"), | |
| Div(style="width: 100%; height: 4px; background-color: #e0e0e0; margin-top: 10px; border-radius: 2px;")( | |
| Div(cls="progress-bar", style="height: 100%; background-color: #007bff; animation: progress 1.5s ease-in-out infinite;") | |
| ) | |
| ) | |
| def stream_drug_info(drug_name): | |
| """Stream drug information from Anthropic API""" | |
| client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) | |
| with client.beta.messages.stream( | |
| model="claude-sonnet-4-5-20250929", | |
| max_tokens=5000, | |
| temperature=1, | |
| system="You are a professional doctor who when given a drug brand name which is given in form of tablets or syrup form, tells me about the following things: * Side Effects - Common and serious adverse effects * Medicinal Usage - Approved therapeutic indications and how it works", | |
| messages=[ | |
| { | |
| "role": "user", | |
| "content": [ | |
| { | |
| "type": "text", | |
| "text": f"Check about the drug brand name: {drug_name}" | |
| } | |
| ] | |
| } | |
| ] | |
| ) as stream: | |
| for text in stream.text_stream: | |
| yield text | |
| class Drug: | |
| drug_name: str | |
| app, rt = fast_app() | |
| def get(): | |
| return Titled("Drug Information Predictor", | |
| Div(cls="container")( | |
| H1("Drug Information Finder"), | |
| P("Enter a drug name to get detailed information about it."), | |
| Form( | |
| id="drug-form", | |
| hx_post="/profile", | |
| hx_target="#results", | |
| hx_indicator="#loader", | |
| hx_swap="innerHTML", | |
| onsubmit="document.getElementById('drug-form').style.display='none';" | |
| )( | |
| Fieldset( | |
| Label('Drug Name:', Br(), Input(name="drug_name", placeholder="e.g., Gelusil", required=True)), | |
| ), | |
| Br(), | |
| Button("Get Drug Info", type="submit", cls="btn-primary"), | |
| ), | |
| create_loader(), | |
| Div(id="results"), | |
| Style(SHARED_STYLES) | |
| ) | |
| ) | |
| def post(drug: Drug): | |
| print(f"Received POST request for drug: {drug.drug_name}") # Debug print | |
| def generate(): | |
| # Hide the loader and show initial response | |
| yield Script(""" | |
| document.getElementById('loader').style.display = 'none'; | |
| """) | |
| yield Div(cls="container")( | |
| H1(f"Drug Information: {drug.drug_name}"), | |
| Div(id="streaming-content", cls="content-box"), | |
| Br(), | |
| A("Search Another Drug", href="/", cls="btn-primary") | |
| ) | |
| # Stream content chunks | |
| for chunk in stream_drug_info(drug.drug_name): | |
| yield Script(f""" | |
| document.getElementById('streaming-content').innerHTML += {repr(chunk)}; | |
| """) | |
| return generate() | |
| serve() | |