# Project export: RemoteClassifier

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: Cal Hacks 10.0
- Tagline: Update your AI database and model automatically
- Devpost: https://devpost.com/software/remoteok
- GitHub: https://github.com/MostafaWahiep/CalHacks
- Demo: https://github.com/Abdulrahmansoliman/Skin-cancer-image-classifier
- Team: 2 GitHub contributor(s) — MostafaWahiep (10 commits), Abdulrahman Soliman (3 commits)

## Devpost submission (written by the team)

### Inspiration

While searching for ideas, our team came across large datasets that needed more effectively classified and were challenging to make predictions based on. Upon examining these datasets, we observed that many could be cleaned and maintained to create models capable of making profound predictions. Following this initial idea, we conceived the idea of developing a website designed to grow exponentially over time, continuously improving its accuracy as we update the models to accommodate expanding datasets. We started by addressing urgent human health issues, such as skin cancer. We developed the website to predict the likelihood of an individual having it, with the support of medical validators, namely doctors.

### What it does

The system comprises the following components: A general user interface in the app, where users can upload images for verification. A cloud-based machine learning algorithm. A validator interface within the app for verifying data (in this case, images) that produce positive results, which can be either true positives or false positives. The workflow involves a continuous data exchange between the general user and the machine learning algorithm to detect anomalies. When a trained outcome is predicted, a notification is sent to the validator, who then assesses whether it's a false positive or an accurate positive prediction. If it's a true positive, the validator verifies it and updates it in the positive dataset. If it's a false positive, the validator does not verify it, and it is not added to the positive dataset. How it works User side: Users can upload images to the model to receive predictions. The model evaluates the image. The result is returned to the user. If the result is positive, the app requests the general user's permission to transfer the image to a validator. Validator side: Upon the upload of images and data, the validator assesses the data's quality. After 100 uploads, the validator decides whether to approve the data. Approved data is seamlessly integrated into the dataset, resulting in an automatic update of the AI model. With the app's help, we can harness the power of big data to develop highly accurate predictive models. Building the system We attempted to create a website using the Reflex development environment to upload images and establish communication with validators to verify them. To accomplish this, we employed a Convolutional Neural Network (CNN) model as our machine learning algorithm, which enabled us to process the continuously incoming data and classify it into "normal" or "abnormal" states. If the data exceeded a threshold for "abnormal" occurrences, we directed it to the validator for verification. Once the validator confirmed the images, we harnessed the capabilities of a database and AI from MindsDB to store and categorize these images. Our models will undergo regular updates using MindsDB's power to enhance accuracy. Consequently, this approach will deliver a more precise and practical prediction application, especially when dealing with large datasets. Example use case Consider a dermatologist using this service to develop and maintain an AI-powered skin cancer detection system. The dermatologist can upload images of skin lesions along with their corresponding diagnoses. Subsequently, the service will train a model for skin cancer detection. The dermatologist can then employ this model to expedite and improve the accuracy of diagnosing new patients. Challenges We faced various challenges and issues throughout this project. Adopting new technologies, such as Reflex and MindsDB, required us to grasp and implement their syntax. Nonetheless, these efforts will yield a more efficient website than current technologies. The second issue we faced was the limited size of our dataset, which restricted our ability to measure accuracy effectively. In the future, it is advisable to test the model with diverse datasets, explore sequential algorithms, and optimize layers and performance. In the current state, lacking a live information feed and a comprehensive dataset, it is challenging to determine issues related to overfitting or underfitting. In the next phase of our remote project, we have several key objectives: We aim to optimize the system's information processing speed when called upon. We plan to expand our network of validators and acquire more datasets to enhance the accuracy of our models. We intend to enable the system to automatically generate reports and provide personalized recommendations based on the models.

## README (from the GitHub repository)

# Twitter Example


## Detected evidence (automated analysis)

Indexed codebase: 39 recognized source files, 100 KB.
- CSS (language) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code

## Codebase structure (from repository index)

### Files (51 of 51)

```
.gitignore
.web/.gitignore
.web/components/reflex/chakra_color_mode_provider.js
.web/components/reflex/radix_themes_color_mode_provider.js
.web/env.json
.web/jsconfig.json
.web/next.config.js
.web/package.json
.web/pages/_app.js
.web/pages/_document.js
.web/pages/404.js
.web/pages/classify.js
.web/pages/index.js
.web/pages/login.js
.web/pages/signup.js
.web/postcss.config.js
.web/reflex.json
.web/styles/code/prism.js
.web/styles/styles.css
.web/styles/tailwind.css
.web/tailwind.config.js
.web/utils/client_side_routing.js
.web/utils/components.js
.web/utils/context.js
.web/utils/helpers/dataeditor.js
.web/utils/state.js
.web/utils/theme.js
alembic.ini
alembic/env.py
alembic/README
alembic/script.py.mako
db_initialization.py
models/model.h5
README.md
reflex.db
requirements.txt
rxconfig.py
twitter/__init__.py
twitter/components/__init__.py
twitter/components/container.py
twitter/layouts/__init__.py
twitter/layouts/auth.py
twitter/pages/__init__.py
twitter/pages/home.py
twitter/pages/home1.py
twitter/pages/login.py
twitter/pages/signup.py
twitter/state/auth.py
twitter/state/base.py
twitter/state/home.py
twitter/twitter.py
```

### Dependencies

- .web/package.json: @chakra-ui/icons@^2.0.19, @chakra-ui/react@^2.6.1, @chakra-ui/system@^2.5.7, @emotion/react@^11.11.0, @emotion/styled@^11.11.0, autoprefixer@10.4.14, axios@1.4.0, focus-visible@5.2.0, framer-motion@^10.16.4, json5@2.2.3, next@13.5.4, next-sitemap@4.1.8, next-themes@0.2.0, postcss@8.4.24, react@18.2.0, react-dom@18.2.0, react-dropzone@^14.2.3, socket.io-client@4.6.1, tailwindcss@^3.3.2, universal-cookie@4.0.4
- requirements.txt: reflex@>=0.2.0

### Recent commits (newest first)

- implemented prediction and insertion
- modified schema and initialized it
- created database schema
- created database schema
- Added CNN model for MNIST dataset
- database engine added
- added database
- l:q
- Merge branch 'main' of https://github.com/MostafaWahiep/CalHacks
- commit
- second commit
- commit
- inital

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

### requirements.txt

```
reflex>=0.2.0

```

### .web/package.json

```
{
  "name": "reflex",
  "scripts": {
    "dev": "next dev",
    "export": "next build && next export -o _static",
    "export-sitemap": "next build && next-sitemap && next export -o _static",
    "prod": "next start"
  },
  "dependencies": {
    "@chakra-ui/icons": "^2.0.19",
    "@chakra-ui/react": "^2.6.1",
    "@chakra-ui/system": "^2.5.7",
    "@emotion/react": "^11.11.0",
    "@emotion/styled": "^11.11.0",
    "axios": "1.4.0",
    "focus-visible": "5.2.0",
    "framer-motion": "^10.16.4",
    "json5": "2.2.3",
    "next": "13.5.4",
    "next-sitemap": "4.1.8",
    "next-themes": "0.2.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-dropzone": "^14.2.3",
    "socket.io-client": "4.6.1",
    "tailwindcss": "^3.3.2",
    "universal-cookie": "4.0.4"
  },
  "devDependencies": {
    "autoprefixer": "10.4.14",
    "postcss": "8.4.24"
  }
}

```

### .web/pages/index.js

```javascript
import { Fragment, useContext, useEffect, useRef, useState } from "react"
import { useRouter } from "next/router"
import { Event, getAllLocalStorageItems, getRefValue, getRefValues, isTrue, preventDefault, refs, set_val, spreadArraysOrObjects, uploadFiles, useEventLoop } from "/utils/state"
import { ColorModeContext, EventLoopContext, initialEvents, StateContext } from "/utils/context.js"
import "focus-visible/dist/focus-visible"
import { Avatar, Box, Button, Grid, Heading, HStack, Input, Link, Modal, ModalBody, ModalContent, ModalHeader, ModalOverlay, Spacer, Text, Textarea, VStack } from "@chakra-ui/react"
import { getEventURL } from "/utils/state.js"
import NextLink from "next/link"
import { AddIcon, RepeatIcon, StarIcon } from "@chakra-ui/icons"
import NextHead from "next/head"



export default function Component() {
  const state = useContext(StateContext)
  const router = useRouter()
  const [ colorMode, toggleColorMode ] = useContext(ColorModeContext)
  const focusRef = useRef();
  
  // Main event loop.
  const [addEvents, connectError] = useContext(EventLoopContext)

  // Set focus to the specified element.
  useEffect(() => {
    if (focusRef.current) {
      focusRef.current.focus();
    }
  })

  // Route after the initial page hydration.
  useEffect(() => {
    const change_complete = () => addEvents(initialEvents())
    router.events.on('routeChangeComplete', change_complete)
    return () => {
      router.events.off('routeChangeComplete', change_complete)
    }
  }, [router])


  return (
    <Fragment>
  <Fragment>
  {isTrue(connectError !== null) ? (
  <Fragment>
  <Modal isOpen={connectError !== null}>
  <ModalOverlay>
  <ModalContent>
  <ModalHeader>
  {`Connection Error`}
</ModalHeader>
  <ModalBody>
  <Text>
  {`Cannot connect to server: `}
  {(connectError !== null) ? connectError.message : ''}
  {`. Check if server is reachable at `}
  {getEventURL().href}
</Text>
</ModalBody>
</ModalContent>
</ModalOverlay>
</Modal>
</Fragment>
) : (
  <Fragment/>
)}
</Fragment>
  <Box sx={{"width": "100%", "maxWidth": "1300px", "bg": "white", "h": "100%", "px": [4, 12], "margin": "0 auto", "position": "relative"}}>
  <Grid sx={{"gridTemplateColumns": "1fr 2fr 1fr", "h": "100vh", "gap": 4}}>
  <Box sx={{"py": 4}}>
  <VStack alignItems={`left`} sx={{"gap": 4}}>
  <Heading size={`md`}>
  {`PySocial`}
</Heading>
  <Link as={NextLink} href={`/`} sx={{"display": "inline-flex", "alignItems": "center", "py": 3, "px": 6, "border": "1px solid #eaeaea", "fontWeight": "semibold", "borderRadius": "full"}}>
  <StarIcon sx={{"mr": 2}}/>
  {`Home`}
</Link>
  <Box sx={{"p": 4, "borderRadius": "md", "border": "1px solid #eaeaea"}}>
  <Heading size={`sm`}>
  {`Followers`}
</Heading>
  {state.home_state.followers.map((dhcrtwpc, i) => (
  <VStack key={i} sx={{"padding": "1em"}}>
  <HStack>
  <Avatar name={dhcrtwpc.follower_username} size={`sm`}/>
  <Text>
  {dhcrtwpc.follower_username}
</Text>
</HStack>
</VStack>
))}
</Box>
  <Button onClick={(_e) => addEvents([Event("state.logout", {})], (_e))}>
  {`Sign out`}
</Button>
</VStack>
</Box>
  <Box sx={{"borderX": "1px solid #ededed", "h": "100%"}}>
  <HStack justify={`space-between`} sx={{"p": 4, "borderBottom": "1px solid #ededed"}}>
  <Heading size={`md`}>
  {`Home`}
</Heading>
  <Input onChange={(_e0) => addEvents([Event("state.home_state.set_search", {search:_e0.target.value})], (_e0))} placeholder={`Search tweets`} type={`text`}/>
</HStack>
  <Grid sx={{"gridTemplateColumns": "1fr 5fr", "borderBottom": "1px solid #ededed"}}>
  <VStack sx={{"p": 4}}>
  <Avatar size={`md`}/>
</VStack>
  <Box>
  <Textarea onBlur={(_e0) => addEvents([Event("state.home_state.set_tweet", {value:_e0.target.value})], (_e0))} placeholder={`What's happening?`} sx={{"w": "100%", "border": 0, "resize": "none", "py": 4, "px": 0, "_focus": {"border": 0, "outline": 0, "boxShadow": "none"}}}/>
  <HStack justifyContent={`flex-end`} sx={{"borderTop": "1px solid #ededed", "px": 4, "py": 2}}>
  <Button onClick={(_e) => addEvents([Event("state.home_state.post_tweet", {})], (_e))} sx={{"bg": "rgb(29 161 242)", "color": "white", "borderRadius": "full"}}>
  {`Tweet`}
</Button>
</HStack>
</Box>
</Grid>
  <Fragment>
  {isTrue(state.home_state.tweets) ? (
  <Fragment>
  {state.home_state.tweets.map((zkwezpiz, i) => (
  <Grid key={i} sx={{"gridTemplateColumns": "1fr 5fr", "py": 4, "gap": 1, "borderBottom": "1px solid #ededed"}}>
  <VStack>
  <Avatar name={zkwezpiz.author} size={`sm`}/>
</VStack>
  <Box>
  <Text sx={{"fontWeight": "bold"}}>
  {("@" + zkwezpiz.author)}
</Text>
  <Text sx={{"width": "100%"}}>
  {zkwezpiz.content}
</Text>
</Box>
</Grid>
))}
</Fragment>
) : (
  <Fragment>
  <VStack sx={{"p": 4}}>
  <Button onClick={(_e) => addEvents([Event("state.home_state.get_tweets", {})], (_e))}>
  <RepeatIcon sx={{"mr": 1}}/>
  <Text>
  {`Click to load tweets`}
</Text>
</Button>
</VStack>
</Fragment>
)}
</Fragment>
</Box>
  <VStack alignItems={`start`} sx={{"gap": 4, "h": "100%", "py": 4}}>
  <Input onChange={(_e0) => addEvents([Event("state.home_state.set_friend", {value:_e0.target.value})], (_e0))} placeholder={`Search users`} sx={{"width": "100%"}} type={`text`}/>
  {state.home_state.search_users.map((bmxbnoie, i) => (
  <VStack key={i} sx={{"py": 2, "width": "100%"}}>
  <HStack sx={{"width": "100%"}}>
  <Avatar name={bmxbnoie.username} size={`sm`}/>
  <Text>
  {bmxbnoie.username}
</Text>
  <Spacer/>
  <Button onClick={(_e) => addEvents([Event("state.home_state.follow_user", {username:bmxbnoie.username})], (_e))}>
  <AddIcon/>
</Button>
</HStack>
</VStack>
))}
  <Box sx={{"p": 4, "borderRadius": "md", "border": "1px solid #eaeaea", "w": "100%"}}>
  <Heading size={`sm`}>
  {`Following`}
</Heading>
  {state.home_state.following.map((xdxcnolr, i) => (
  <VStack key={i} sx={{"padding": "1em"}}>
  <HStack>
  <Avatar name={xdxcnolr.followed_username} size={`sm`}/>
  <Text>
  {xdxcnolr.followed_username}
</Text>
</HStack>
</VStack>
))}
</Box>
</VStack>
</Grid>
</Box>
  <NextHead>
  <title>
  {`
[truncated — 165 more characters]
```

### rxconfig.py

```python
import reflex as rx

config = rx.Config(
    app_name="twitter",
    db_url="sqlite:///reflex.db",
)

```

### db_initialization.py

```python
import reflex as rx
from twitter.state.base import *

with rx.session() as session:
    user1 = User(username="yes", password="yes")
    user2 = User(username="no", password="no")
    session.add(user1)
    session.add(user2)
    session.commit()

    val1 = Validator(username="tam", password="tam")
    val2 = Validator(username="tri", password="tri")
    session.add(val1)
    session.add(val2)
    session.commit()

    model1 = Model(name="Skin Cancer", dataset="dataset1", notebook="notebook1", model_file="model_file1", dataset_size=10000, validators=[val1, val2])
    model2 = Model(name="Natural Images", dataset="dataset2", notebook="notebook2", model_file="model_file2", dataset_size=20000, validators=[val2])
    session.add(model1)
    session.add(model2)
    session.commit()

    label1 = Label(name='Actinic Keratoses', model_id=model1.id)
    label2 = Label(name='Basal Cell Carcinoma', model_id=model1.id)
    label3 = Label(name='Benign Keratosis', model_id=model1.id)
    label4 = Label(name='Dermatofibroma', model_id=model1.id)
    label5 = Label(name='Melanocytic Nevi', model_id=model1.id)
    label6 = Label(name='Melanoma', model_id=model1.id)
    label7 = Label(name='Vascular Lesions', model_id=model1.id)
    session.add(label1)
    session.add(label2)
    session.add(label3)
    session.add(label4)
    session.add(label5)
    session.add(label6)
    session.add(label7)
    session.commit()

    label8 = Label(name='Airplane', model_id=model2.id)
    label9 = Label(name='Car', model_id=model2.id)
    label10 = Label(name='Cat', model_id=model2.id)
    label11 = Label(name='Dog', model_id=model2.id)
    label12 = Label(name='Flower', model_id=model2.id)
    label13 = Label(name='Fruit', model_id=model2.id)
    session.add(label8)
    session.add(label9)
    session.add(label10)
    session.add(label11)
    session.add(label12)
    session.add(label13)
    session.commit()


```

### .web/postcss.config.js

```javascript
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### .web/next.config.js

```javascript
module.exports = {
  basePath: "",
  compress: true,
  reactStrictMode: true,
  trailingSlash: true,
};

```

### .web/tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
	content: ["./pages/**/*.{js,ts,jsx,tsx}"],
	theme: null,
	plugins: [
	],
};
```

### twitter/twitter.py

```python
"""Welcome to Reflex! This file outlines the steps to create a basic app."""
import reflex as rx

from .pages import home, login, signup, home1
from .state.base import State

app = rx.App(state=State)
app.add_page(login)
app.add_page(signup)
app.add_page(home, route="/", on_load=State.check_login())
app.add_page(home1, route="/classify", on_load=State.check_login())
app.compile()

```

### alembic/env.py

```python
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
    fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = None

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online() -> None:
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    connectable = engine_from_config(
        config.get_section(config.config_ini_section, {}),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        with context.begin_transaction():
            context.run_migrations()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

```

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