Creating a web app with deno, fresh and Tensorflow

I created a tool.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan

Last week I got a trained a simple model that will detect if an image looks like a link or a button. It was fun and I learnt a lot.

This article is less about the ML model and more about how I made a TensorflowJS Preact Component using Deno and Fresh and some of the snags I hit so that you don't have to hit them.

The Demo itself might not make sense, so I will give some context first. I trained the ML model in Google Colab, and while it has a handy little script that lets me upload files it is incredibly slow, so I wanted a way to drag and drop many images on a page and have it automatically classify the images. If you try the demo just take a screen shot of a button or a link with about 10px of padding around it like so ) and it will output something like the following:

The output of the ML model

I also wanted an excuse to get a model into "production".

The Code is built around Deno and Fresh, and broadly it was a lot of fun to get started. I really liked how quick it is to deploy (feels significantly faster than Vercel). I did struggle with the documentation, for example the docs around islands are sparse and it implies that it runs in the client - so I naturally thought I could just include my file-drop Custom Element, however I ran in to a number of problems where because it is rendering on the server it doesn't have access to DOM Element APIs and thus would not buidl. I had to rely on a handy hint from Luca Casonato.

if (IS_BROWSER) {
  await import("https://esm.sh/file-drop-element");
}

After that, using the Web Component in an island is just like using it in the browser.

interface FileDropProps {
  accept: string;
  multiple?: boolean;
}

export default function FileDrop(props: FileDropProps) {
  const [accept] = useState(props.accept);
  const [multiple] = useState(props.multiple);
  const tensorFlow = useRef(null);
  let [files, setFiles] = useState("");
  let x: FileDropEvent;

  const onFileDrop: FileDropEvent = (event) => {
    setFiles(event.files);
  }

  const onFileSelect: Event = (event) => {
    setFiles(event.target.files);
  }

  return (
    <div>
      <file-drop onfiledrop={onFileDrop} accept={accept} multiple={multiple}>
	...
  )
}

Although now that I think about it, is it just a functionless element sent on the request? I should check... It feels like the docs could be a little clearer.

Integrating TensorFlow was surprisingly straight forwards (and can be seen completely here).

The first thing that I had to do was include Tensorflow as a global <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script> on my index route, and then I created the component as follows.

export function TensorFlow({ url, files }) {
  const [model, setModel] = useState();
  const [predictions, setPredictions] = useState();

  useEffect(async () => {
    const newModel = await tf.loadLayersModel(url);

    setModel(newModel);
  }, [url]); // When the URL changes, refetch the model

  useEffect(async () => {
    console.log("Analysing", files);

    const predictionsResults: PredictionResult[] = []
    for (const file of files) {
      const fileUrl = URL.createObjectURL(file)
      predictionsResults.push({ prediction: await analyse(fileUrl, model), fileUrl });
    }

    setPredictions(predictionsResults);
  }, [files]);

  return (
    <div>
      <h2>Prediction </h2>
      <div>{model == null ? 'Loading Model' : (predictions != null) ? renderPredictions(predictions) : ''}</div>
    </div>
  );
}

And it can be used as follows <TensorFlow url="/model/model.json" files={files} ref={tensorFlow}></TensorFlow>.

I was quite happy with this structure because it allows you to control which model TensorFlow should use, and which files it accepts (which is specific to my usecase).

The only thing that is special here is that I only want to instantiate the model when the property changes, and I only want to run the prediction when the input files array changes.

And that's it. It just worked.

Next up will be integrating this Tensorflow model into a custom Lighthouse Audit.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan


Print Share Comment Cite Upload Translate Updates
APA

Paul Kinlan | Sciencx (2023-01-12T11:10:43+00:00) Creating a web app with deno, fresh and Tensorflow. Retrieved from https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/

MLA
" » Creating a web app with deno, fresh and Tensorflow." Paul Kinlan | Sciencx - Thursday January 12, 2023, https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/
HARVARD
Paul Kinlan | Sciencx Thursday January 12, 2023 » Creating a web app with deno, fresh and Tensorflow., viewed ,<https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/>
VANCOUVER
Paul Kinlan | Sciencx - » Creating a web app with deno, fresh and Tensorflow. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/
CHICAGO
" » Creating a web app with deno, fresh and Tensorflow." Paul Kinlan | Sciencx - Accessed . https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/
IEEE
" » Creating a web app with deno, fresh and Tensorflow." Paul Kinlan | Sciencx [Online]. Available: https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/. [Accessed: ]
rf:citation
» Creating a web app with deno, fresh and Tensorflow | Paul Kinlan | Sciencx | https://www.scien.cx/2023/01/12/creating-a-web-app-with-deno-fresh-and-tensorflow/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.