# Project export: SageWell

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: An AI-powered Medical Assistant for the Elderly
- Devpost: https://devpost.com/software/sagewell
- GitHub: https://github.com/PrabhleenKaurLamba/SageWell
- Video: https://www.youtube.com/embed/y6nkSYeK0pA?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Best Use of Monster Generative AI APIs (4x XBox Series S [1st] & 1 million Monster API credits [2nd] & $400 Cash [3rd]))
- Team: 1 GitHub contributor(s) — Prabhleen Kaur Lamba (2 commits)

## Devpost submission (written by the team)

### Inspiration

Our inspiration for creating this AI project stemmed from the desire to leverage current technology to enhance the lives of our community members, particularly the elderly. Recognizing the difficulties faced by aging individuals, including our own grandparents, to embrace technological advancements, and their concerns about health conditions, we sought a way to integrate technology and healthcare services seamlessly into their lives. Thus, SageWell was conceived—an AI companion designed to provide personalized support to seniors by navigating medical information alongside their healthcare providers. At SageWell, we believe in accessibility of AI for all age groups.

### What it does

SageWell enables users to seek medical information through natural language interactions, allowing elderly individuals to pose questions verbally and receive spoken responses, mimicking human conversation.

### How we built it

SageWell leverages the capabilities of two Monster APIs: OpenAI-Whisper Large-v2 for speech-to-text conversion and Meta's llama-2-7b-chat-hf for refining our reinforcement learning model. Our model was trained on MedQuAD, a comprehensive dataset containing over 47,000 medical question-answer pairs, Drugs, Side Effects and Medical Condition dataset, and Drugs Related to Medical Conditions dataset. The frontend of the web app was built using React, a JavaScript library, and the service we integrated into our app to store all the audio files was Firebase.

### Challenges we ran into

In the process of developing SageWell, we encountered several challenges. Since there were many integrations in our application, from speech-to-text transcription and MonsterAPIs for fine-tuned LLMs, to storage service providers, we faced difficulties trying to link all the individual pieces together. We learned several new tools and technologies and also spent time fine-tuning models to provide medical information. Additionally, we encountered setbacks when we were finishing up our project as we were facing CORS errors when making API calls from the browser - we were able to work around this by adding a proxy, which served as a bridge between our client and server.

### Accomplishments we're proud of

We empowered our primary user demographic, the elderly, to engage with SageWell through voice interactions instead of having to type text. We addressed the challenges that many seniors encounter when typing on digital devices, thereby increasing the accessibility of the process of seeking medical information and ensuring inclusivity in AI for all age groups, especially the elderly. Our reinforcement learning model has demonstrated effectiveness, evidenced by the decrease in training loss after each iteration and to 0.756 at the end. This indicates that the model fits well on the training data. We merged three datasets: the Medical Question Answering data set, the Drugs, Side Effects and Medical Condition data set, and the Drugs Related to Medical Conditions data set. By training our model for SageWell on these datasets obtained from NIH websites and drugs.com, we allowed SageWell to provide medical information to users based on reliable, comprehensive databases.

### What we learned

Through this project, we gained valuable insights into the startup ecosystem and developer space. We expanded our skill set by refining our model, working with new APIs and storage providers, and creating a solution that addresses the specific challenges faced by our target audience.

### What's next

The journey of SageWell is just beginning. Moving forward, we aim to expand its capabilities to assist in additional areas crucial for the well-being of the elderly, such as medication reminders and guidance on accessing support for domestic chores. Furthermore, we envision integrating features that facilitate connections between seniors and younger generations, including their grandchildren and other youth in their communities. By fostering these intergenerational connections, SageWell will expand its targeting market size by not only keeping the elderly engaged with their loved ones but also ensuring they remain connected to the evolving world around them. Through SageWell, we look forward to continuing to push for accessibility of AI for all age groups.

## README (from the GitHub repository)

# SageWell, an AI-powered Medical Assistant for the Elderly | Stanford TreeHacks 2024 Prize Winner

https://devpost.com/software/sagewell

https://youtu.be/y6nkSYeK0pA

![image](https://github.com/PrabhleenKaurLamba/SageWell/assets/59297291/4edc1780-40f9-4a26-8f0e-50cbe506e2b0)

![image](https://github.com/PrabhleenKaurLamba/SageWell/assets/59297291/b6d8ad5a-f9f9-4534-b286-4486ea8301f1)


## Detected evidence (automated analysis)

Indexed codebase: 11 recognized source files, 22 KB.
- CSS (language) — detected in the code
- Firebase (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code

## Codebase structure (from repository index)

### Files (17 of 17)

```
.firebaserc
.gitignore
firebase.json
package.json
public/index.html
public/manifest.json
public/robots.txt
README.md
src/css/Assistant.css
src/css/Home.css
src/firebase.js
src/index.css
src/index.js
src/Pages/Assistant.js
src/Pages/Home.js
src/reportWebVitals.js
src/setupTests.js
```

### Dependencies

- package.json: @fortawesome/fontawesome-free@^6.5.1, @testing-library/jest-dom@^5.17.0, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, firebase@^10.8.0, mic-recorder-to-mp3@^2.2.2, monsterapi@^0.0.3, react@^18.2.0, react-dom@^18.2.0, react-icons@^5.0.1, react-router-dom@^6.22.1, react-scripts@5.0.1, web-vitals@^2.1.4

### Recent commits (newest first)

- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- add UI and new api for model
- format string
- merged APIs
- test
- added monster api call
- implemented text to speech
- initial commit
- Initialize project using Create React App

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "treehacks",
  "version": "0.1.0",
  "private": true,
  "proxy": "https://23c0047b-044d-4b61-8822-91d103c68f85.monsterapi.ai",
  "dependencies": {
    "@fortawesome/fontawesome-free": "^6.5.1",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "firebase": "^10.8.0",
    "mic-recorder-to-mp3": "^2.2.2",
    "monsterapi": "^0.0.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-icons": "^5.0.1",
    "react-router-dom": "^6.22.1",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```

### src/index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
import './index.css';
import HomePage from './Pages/Home';
import Assistant from './Pages/Assistant';
import reportWebVitals from './reportWebVitals';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/assistant" element={<Assistant />} />
        <Route path="*" element={<Navigate to="/" />} />
      </Routes>
    </BrowserRouter>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();
```

### src/setupTests.js

```javascript
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

```

### src/reportWebVitals.js

```javascript
const reportWebVitals = onPerfEntry => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;

```

### src/index.css

```css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}
```

### src/firebase.js

```javascript
// // Import the functions you need from the SDKs you need
// import { initializeApp } from "firebase/app";
// import { getStorage } from "./firebase/storage"
// // TODO: Add SDKs for Firebase products that you want to use
// // https://firebase.google.com/docs/web/setup#available-libraries

import { initializeApp } from "firebase/app";

// Your web app's Firebase configuration
const firebaseConfig = {
    apiKey: "AIzaSyCK1JhypC57k0-ZaZCh0AF_m3Gr7-8C7W4",
    authDomain: "treehacks-8cd81.firebaseapp.com",
    projectId: "treehacks-8cd81",
    storageBucket: "treehacks-8cd81.appspot.com",
    messagingSenderId: "684110143182",
    appId: "1:684110143182:web:a617b98bc5ca0ac259ba9f"
  };

// Initialize Firebase
const app = initializeApp(firebaseConfig);

export { app }; // Export the initialized Firebase app

```

### public/index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>SageWell</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" />

  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

```

### src/Pages/Home.js

```javascript
import React from 'react';
import logo from './../img/logo.png';
import './../css/Home.css';

const HomePage = () => {
    const goToHome = () => {
        window.location.href = "/";
    };

    const goToAssistant = () => {
        window.location.href = "/assistant";
    };

    return (
        <div className="home-page">
            <div className="logo-container">
                <img src={logo} alt="SageWell Logo" className="logo" onClick={goToHome} />
            </div>
            <div className="title-container">
                <h1 className="title">Welcome to SageWell, an AI-powered Medical Assistant for the Elderly</h1>
            </div>
            <div className="subtitle">
                <h2>We believe in accessibility of AI for all age groups!</h2>
            </div>
            <button className="try-button" onClick={goToAssistant}>Try it now!</button>
            <div className="subtitle">
                <h2>You may ask</h2>
            </div>
            <div className="suggested-questions">
                <div className="question-box" onClick={goToAssistant}>
                    <div className='text-box'>
                    <p>What are the symptoms of Diabetes? <a className="ask-now" href="/assistant">Ask now</a></p>
                    </div>
                </div>
                <div className="question-box" onClick={goToAssistant}>
                    <div className='text-box'>
                    <p>What causes diabetes? <a className="ask-now" href="/assistant">Ask now</a></p>
                    </div>
                </div>
                <div className="question-box" onClick={goToAssistant}>
                    <div className='text-box'>
                    <p>How do I treat diabetes? <a className="ask-now" href="/assistant">Ask now</a></p>
                    </div>
                </div>
                <div className="question-box" onClick={goToAssistant}>
                <div className='text-box'>
                    <p>What doctor should I see for diabetes? <a className="ask-now" href="/assistant">Ask now</a></p>
                </div>
                </div>
            </div>
            <footer className="footer">
                TreeHacks @ 2024
            </footer>
        </div>
    );
};

export default HomePage;

```

### src/css/Home.css

```css
.home-page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start; /* Align content to the top */
min-height: 100vh; /* Use min-height instead of height to ensure content fits within the viewport */
background-color: #2B2C33; /* Space Grey background */
}

.title-container {
margin-top: 20vh; /* Adjust the top margin as needed */
display: flex;
justify-content: center;
}

.title {
font-family: 'Kode Mono', monospace;
background-image: linear-gradient(to right, orange, purple, rgb(57, 57, 176));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-size: 2rem;
text-align: center;
max-width: 65%;
font-weight: bold; /* Adjust font weight for the title */
}
.subtitle {
margin-top: 20px;
font-family: 'Kode Mono', monospace;
font-size: 0.8rem;
color: grey; /* White text color */
font-weight: lighter; /* Adjust font weight for the subtitle */
}


.try-button {
margin-top: 20px; 
padding: 12px 24px; 
background-color: #ffffff; 
font-family: 'Kode Mono', monospace;
color: #2B2C33; 
border: 2px solid #4b4b51; 
border-radius: 25px; 
font-size: 1rem;
width: auto; 
text-decoration: none; /* Remove default link underline */
cursor: pointer; /* Change cursor to pointer on hover */
display: inline-block; /* Ensures button is displayed inline */
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; /* Added color and border transition */
}

.try-button:hover {
background-color: #4b4b51; /* Darker green on hover */
border-color: #4b4b51; /* Darker border color on hover */
}

.footer {
background-color: #2B2C33;
font-family: 'Kode Mono', monospace;
color: #ffffff; 
text-align: center;
padding: 20px 0; 
position: fixed; 
width: 100%; 
bottom: 0; 
}

.logo-container {
position: absolute;
top: 30px; /* Adjust top position as needed */
left: 30px; /* Adjust left position as needed */
cursor: pointer; /* Change cursor to pointer on hover */
}

.logo {
width: 70px; /* Adjust width as needed */
height: auto; /* Maintain aspect ratio */
}

.suggested-questions {
    display: flex;
    flex-wrap: wrap; /* Allow wrapping of question boxes */
    width: 80%; /* Adjust width as needed */
    margin-top: 20px;
    justify-content: center;
}

.question-box {
    display: flex; /* Add flexbox */
    flex-direction: column; /* Arrange children vertically */
    align-items: center; /* Center-align items horizontally */
    background-color: #38393e;
    padding: 20px; /* Adjust padding as needed */
    border-radius: 10px;
    box-sizing: border-box; /* Include padding in width calculation */
    margin-right: 10px; /* Add right margin */
    margin-bottom: 10px; /* Add bottom margin */
    width: 20%; /* Adjust width as needed */
}

.text-box {
    flex: 1; /* Grow to fill available space */
    color: #cdcecf;
    margin-bottom: 10px; /* Add bottom margin to separate from "Ask now" */
}

.ask-now {
    text-decoration: underline;
    color: #8d8e91; /* or any other color you prefer */
}

.ask-now:hover {
    color: #8d8e91; /* Change color on hover */
}


```

### src/css/Assistant.css

```css
.home-page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start; /* Align content to the top */
min-height: 100vh; /* Use min-height instead of height to ensure content fits within the viewport */
background-color: #2B2C33; /* Space Grey background */
}
.logo-container {
position: absolute;
top: 30px; /* Adjust top position as needed */
left: 30px; /* Adjust left position as needed */
cursor: pointer; /* Change cursor to pointer on hover */
}

.logo {
width: 70px; /* Adjust width as needed */
height: auto; /* Maintain aspect ratio */
}    

.title-container2 {
    margin-top: 20px; /* Reduce the top margin to bring the title closer to the logo */
    display: flex;
    justify-content: center;
}

.title2 {
    font-family: 'Kode Mono', monospace;
    background-image: linear-gradient(to right, orange, purple, rgb(57, 57, 176));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-size: 2rem;
    text-align: center;
    max-width: 100%; /* Adjust the max-width as needed */
    font-weight: bold;
    white-space: nowrap; /* Prevent line breaks */
}



.subtitle {
margin-top: 20px;
font-family: 'Kode Mono', monospace;
font-size: 0.8rem;
color: grey; /* White text color */
font-weight: lighter; /* Adjust font weight for the subtitle */
}

.footer {
background-color: #2B2C33;
font-family: 'Kode Mono', monospace;
color: #ffffff; 
text-align: center;
padding: 20px 0; 
position: fixed; 
width: 100%; 
bottom: 0; 
}

.input-container {
    position: fixed;
    bottom: 70px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px;
    background-color: #38393e;
    border-radius: 10px;
    width: 35%;
}

.input-container p {
    margin: 0; /* Remove default margin */
    padding: 10px; /* Add padding to the text */
    flex-grow: 1; /* Allow the text to take up remaining space */
    color: #ffffff;
}

.record-button, .send-button {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 20px;
    padding: 5px;
}

.record-button:hover {
    color: #666; /* Darker gray color on hover */
}
.send-button:hover {
    color: greenyellow; /* Change color to red when recording */
}

.record-button.recording {
    color: red; /* Change color to red when recording */
}

.audio-input {
    position: relative; /* Change to relative positioning */
    margin-bottom: 20px; /* Add margin between the two boxes */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    background-color: #38393e;
    border-radius: 10px;
    width: 60%;
    height: auto;
}

.audio-input p {
    margin: 0; /* Remove default margin */
    padding: 10px; /* Add padding to the text */
    color: #ffffff;
    width: 90%;
    word-wrap: break-word; /* Wrap long words */
    line-height: 25px; /* Adjust the line height to add spacing between lines */
}

.audio-input p strong {
    font-weight: bold; /* Make the text bold */
}

.text-output {
    position: relative; /* Change to relative positioning */
    margin-bottom: 20px; /* Add margin between the two boxes */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    background-color: #38393e;
    border-radius: 10px;
    width: 60%;
    height: auto;
}

.text-output p {
    margin: 0; /* Remove default margin */
    padding: 10px; /* Add padding to the text */
    color: #ffffff;
    width: 90%;
    word-wrap: break-word; /* Wrap long words */
    line-height: 25px; /* Adjust the line height to add spacing between lines */
}

.text-output p strong {
    font-weight: bold; /* Make the text bold */
}

.audio-output {
    position: relative; /* Change to relative positioning */
    margin-bottom: 20px; /* Add margin between the two boxes */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    background-color: #38393e;
    border-radius: 10px;
    width: 60%;
    height: auto;
}

.audio-output p {
     margin: 0; /* Remove default margin */
    padding: 10px; /* Add padding to the text */
    color: #ffffff;
    width: 90%;
    word-wrap: break-word; /* Wrap long words */
    line-height: 25px; /* Adjust the line height to add spacing between lines */
}


.text-container {
    flex-basis: 100%; /* Take up full width */
    order: 1; /* Make sure the text container appears before the button container */
}

.button-container {
    flex-basis: 100%; /* Take up full width */
    order: 2; /* Make sure the button container appears after the text container */
    margin-top: 20px; /* Adjust as needed for spacing */
}

.audio-output p strong {
    font-weight: bold; /* Make the text bold */
}

.text-to-speech-button {    
    background-color: transparent;
    border: none;
    cursor: pointer;
    font-size: 24px;
    color: black;
    outline: none;
    padding: 0;
    transition: color 0.2s;
  }
  .text-to-speech-button:hover {
    color: red; /* Change to your preferred hover color */
  }
```

[1 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]