An Elegant Web Application Architecture for Contemporary Times
It used to be that as data scientists we rarely built full-stack production applications. However, that is changing fast due to generative AI (GenAI). Unlike 'traditional' ML models - which are consumed mostly in the background somewhere - GenAI models are front and center - as their output is consumed directly by humans in (most cases). User experience (UX) is now major factor in AI/ML.
Applied data scientists need to double duty as application developers to keep overall solution delivery costs down. In the default case, the time/effort spent on training GenAI models is low to non-existent as most use pre-trained models. 'Training' now consists of prompt design / engineering - along with other tuning techniques e.g. vectorization and indexing strategies for Retrieval Augmented Generation (RAG). The time saved on training (and other ML activities) can now be used for application development, instead.
Traditional web application development (JavaScript/React/Angular/Node.js + [backend]) is still hard and costly. Top-tier web developers are expensive and hard to find; (secretly I think their value comes from their ability to tame CSS gremlins). Users want solutions now, with good UX, and spinning up a new app dev team does not have to be the obvious next step.
Rise of Functional Reactive Programming
Angular and React JavaScript frameworks are the staples of web development today. Their roots lie in a thread of computer science dating back to the late 1990's known as Functional Reactive Programming or FRP. The Reactive Manifesto is a crystallization of FRP ideas. Elm (Haskell-derived) is the language most identified with FRP.
FRP key concepts are:
FRP web frameworks also implement virtual DOM. The changes to the UI elements are first applied to a virtual DOM. The real UI elements are updated by 'diffing' the virtual and real DOMs such that only what has truly changed is updated. This reduces flickering and jitter.
Note the term 'functional' in FRP. Functional programming languages (e.g. Haskell, F#, etc.) are naturally suited to FRP, due to their support of immutable functional data structures.
'Web' Application Architecture - that abstracts away much of the web
JavaScript programming is not for mere mortals like us data scientists (ok that is excessive but still...). Fortunately, there is now WebAssembly (wasm)- a runtime supported by all browsers that can run programs written in essentially any language (even 'C'!).
However, wasm by itself is not enough as we still need a UI framework, i.e. something that will create HTML (and run some JavaScript) in the browser.
Here is a web application stack that fits the bill (there may be others) for creating very usable GenAI applications:
How its all put together and the main features of the stack are described next.
领英推荐
F# FRP Web Stack - Features and Flow
The key here is that almost all application logic (and any associated UI) is written is a single language F# - be it the server side or the browser side. There is some but minimal JavaScript/CSS/HTML creation required.
Furthermore, with Elmish (FRP) one can create a highly interactive applications that are modular and easy to maintain. As per FRP, all application state is modified by messages. Here the messages can be generated on the browser side (by say user interaction). Or can come from the server side!
GenAI models may take up to a full minute to generate a response. For good UX, its crucial to stream GenAI model output to the UI as its being generated (to the extent possible). Robust, real-time two-way communication between browser and server means that users are not left in limbo watching a 'spinner'. Instead, they can see generated chunks of text (and any server-generated notifications) in real-time.
As shown in the FRP Message Flow diagram (above), the Elmish 'hub' is responsible for serializing all incoming messages and updating the application state (via the 'Update' function). The application state is rendered into a virtual 'View'. The view is then reflected into the actual browser DOM. Rapid multiple updates may be combined together to reduce jitter.
Caveats
The main drawback of the proposed approach is that it is hard to design the UI quickly. There are no good UI editors (that I know of). One has to build and run the application to view what the UI looks like after each update. Because the application has to be compiled and packaged into WebAssembly first, this process is comparatively slow (i.e. as compared to traditional web development).
Also, you can't entirely escape from the aforementioned CSS gremlins. There are times when custom CSS is required to make the application look just so. However, this is not inherently an issue of the proposed web stack. ChatGPT helped to resolve many CSS issues!
Summary
Caveats asides, the stack works quite well in practice. We have one GenAI application in production and several in the pipeline. Rapid adoption is due to good UX; quick turnaround; and low cost of development and deployment. This stack was arrived at after evaluating several options (including a traditional web stack with Python backend).
The source code for a generic GenAI application based on the proposed stack is in this GitHub repo. Also, this file provides a view into how Elmish messages are handled by the Update function.
Data Scientist/Gen. AI Strategist in the telecom industry
1 年Introducing the new "Contemporary Web Stack" (CoWS). Suitable for building Generative AI driven applications. https://github.com/fwaris/CW1