📗 That is the sequence on creating net functions with generative AI integration. Half 1 centered on explaining the AI stack and why the applying layer is the most effective place within the stack to be. Test it out here.
Desk of Contents
Introduction
It’s not usually that you just hear the Ruby language talked about when discussing AI.
Python, after all, is the king on this world, and for good motive. The group has coalesced across the language. Most mannequin coaching is completed in PyTorch or TensorFlow today. Scikit-learn and Keras are additionally extremely popular. RAG frameworks corresponding to LangChain and LlamaIndex cater primarily to Python.
Nonetheless, in relation to constructing net functions with AI integration, I imagine Ruby is the higher language.
Because the co-founder of an agency devoted to constructing MVPs with generative AI integration, I regularly hear potential shoppers complaining about two issues:
- Functions take too lengthy to construct
- Builders are quoting insane costs to construct customized net apps
These complaints have a typical supply: complexity. Fashionable net apps have much more complexity in them than within the good ol’ days. However why is that this? Are the advantages introduced by complexity value the price?
I believed spas have been imagined to be enjoyable?
One massive piece of the puzzle is the latest rise of single-page functions (SPAs). The most well-liked stack used at this time in constructing trendy SPAs is MERN (MongoDB, Specific.js, React.js, Node.js). The stack is common for a couple of causes:
- It’s a JavaScript-only stack, throughout each front-end and back-end. Having to solely code in just one language is fairly good!
- SPAs can supply dynamic designs and a “clean” person expertise. Clean right here signifies that when some piece of information adjustments, solely part of the positioning is up to date, versus having to reload the entire web page. In fact, if you happen to don’t have a contemporary smartphone, SPAs received’t really feel so clean, as they are usually fairly heavy. All that JavaScript begins to tug down the efficiency.
- There’s a massive ecosystem of libraries and builders with expertise on this stack. That is fairly round logic: is the stack common due to the ecosystem, or is there an ecosystem due to the recognition? Both manner, this level stands.
React was created by Meta. - A lot of cash and energy has been thrown on the library, serving to to shine and promote the product.
Sadly, there are some downsides of working within the MERN stack, essentially the most important being the sheer complexity.
Conventional net improvement was carried out utilizing the Mannequin-View-Controller (MVC) paradigm. In MVC, all the logic managing a person’s session is dealt with within the backend, on the server. One thing like fetching a person’s information was carried out by way of operate calls and SQL statements within the backend. The backend then serves absolutely constructed HTML and CSS to the browser, which simply has to show it. Therefore the identify “server”.
In a SPA, this logic is dealt with on the person’s browser, within the frontend. SPAs must deal with UI state, software state, and generally even server state all within the browser. API calls must be made to the backend to fetch person information. There may be nonetheless fairly a little bit of logic on the backend, primarily exposing information and performance via APIs.
For instance the distinction, let me use the analogy of a industrial kitchen. The client would be the frontend and the kitchen would be the backend.
Conventional MVC apps are like eating at a full-service restaurant. Sure, there may be loads of complexity (and yelling, if The Bear is to be believed) within the backend. However the frontend expertise is straightforward and satisfying: all the client has to do is decide up a fork and eat their meals.
SPAs are like consuming at a buffet-style eating restaurant. There may be nonetheless fairly a little bit of complexity within the kitchen. However now the client additionally has to resolve what meals to seize, the way to mix them, the way to prepare them on the plate, the place to place the plate when completed, and so on.
Andrej Karpathy had a tweet lately discussing his frustration with trying to construct net apps in 2025. It may be overwhelming for these new to the area.
In an effort to construct MVPs with AI integration quickly, our company has determined to forgo the SPA and as a substitute go together with the standard MVC strategy. Specifically, we’ve discovered Ruby on Rails (usually denoted as Rails) to be the framework greatest suited to rapidly growing and deploying high quality apps with AI integration. Ruby on Rails was developed by David Heinemeier Hansson in 2004 and has lengthy been often called a terrific net framework, however I’d argue it has lately made leaps in its capability to include AI into apps, as we’ll see.
Django is the most well-liked Python net framework, and likewise has a extra conventional sample of improvement. Sadly, in our testing we discovered Django was merely not as full-featured or “batteries included” as Rails is. As a easy instance, Django has no built-in background job system. Practically all of our apps incorporate background jobs, so to not embody this was disappointing. We additionally want how Rails emphasizes simplicity, with Rails 8 encouraging builders to easily self-host their apps as a substitute of going via a supplier like Heroku. Additionally they lately launched a stack of instruments meant to interchange exterior services like Redis.
“However what concerning the clean person expertise?” you may ask. The reality is that trendy Rails contains a number of methods of crafting SPA-like experiences with out all the heavy JavaScript. The first instrument is Hotwire, which bundles instruments like Turbo and Stimulus. Turbo permits you to dynamically change items of HTML in your webpage with out writing customized JavaScript. For the occasions the place you do want to incorporate customized JavaScript, Stimulus is a minimal JavaScript framework that permits you to just do that. Even if you wish to use React, you are able to do so with the react-rails gem. So you’ll be able to have your cake, and eat it too!
SPAs should not the one motive for the rise in complexity, nonetheless. One other has to do with the appearance of the microservices structure.
Microservices are for Macrocompanies
As soon as once more, we discover ourselves evaluating the straightforward previous with the complexity of at this time.
Prior to now, software program was primarily developed as monoliths. A monolithic software signifies that all of the totally different elements of your app — such because the person interface, enterprise logic, and information dealing with — are developed, examined, and deployed as one single unit. The code is all usually housed in a single repo.
Working with a monolith is straightforward and satisfying. Working a improvement setup for testing functions is simple. You might be working with a single database schema containing your whole tables, making queries and joins simple. Deployment is straightforward, because you simply have one container to have a look at and modify.
Nonetheless, as soon as your organization scales to the dimensions of a Google or Amazon, actual issues start to emerge. With lots of or hundreds of builders contributing concurrently to a single codebase, coordinating adjustments and managing merge conflicts turns into more and more troublesome. Deployments additionally turn into extra complicated and dangerous, since even minor adjustments can blow up your entire software!
To handle these points, massive firms started to coalesce across the microservices structure. It is a fashion of programming the place you design your codebase as a set of small, autonomous providers. Every service owns its personal codebase, information storage, and deployment pipelines. As a easy instance, as a substitute of stuffing your whole logic relating to an OpenAI shopper into your primary app, you’ll be able to transfer that logic into its personal service. To name that service, you’ll then usually make REST calls, versus operate calls. This ups the complexity, however resolves the merge battle and deployment points, since every crew within the group will get to work on their very own island of code.
One other profit to utilizing microservices is that they permit for a polyglot tech stack. Which means every crew can code up their service utilizing no matter language they like. If one crew prefers JavaScript whereas one other likes Python, that is no difficulty. Once we first started our company, this concept of a polyglot stack pushed us to make use of a microservices structure. Not as a result of we had a big crew, however as a result of we every wished to make use of the “greatest” language for every performance. This meant:
- Utilizing Ruby on Rails for net improvement. It’s been battle-tested on this space for many years.
- Utilizing Python for the AI integration, maybe deployed with one thing like FastAPI. Severe AI work requires Python, I used to be led to imagine.
Two totally different languages, every centered on its space of specialty. What may go flawed?
Sadly, we discovered the method of improvement irritating. Simply organising our dev atmosphere was time-consuming. Having to wrangle Docker compose information and handle inter-service communication made us want we may return to the wonder and ease of the monolith. Having to make a REST name and arrange the suitable routing in FastAPI as a substitute of constructing a easy operate name sucked.
“Certainly we are able to’t develop AI apps in pure Ruby,” I believed. After which I gave it a attempt.
And I’m glad I did.
I discovered the method of growing an MVP with AI integration in Ruby very satisfying. We have been in a position to dash the place earlier than we have been jogging. I liked the emphasis on magnificence, simplicity, and developer happiness within the Ruby group. And I discovered the state of the AI ecosystem in Ruby to be surprisingly mature and getting higher every single day.
In case you are a Python programmer and are scared off by studying a brand new language like I used to be, let me consolation you by discussing the similarities between the Ruby and Python languages.
Ruby and Python: Two Sides of the Identical Coin
I contemplate Python and Ruby to be like cousins. Each languages incorporate:
- Excessive-level Interpretation:Â This implies they summary away loads of the complexity of low-level programming particulars, corresponding to reminiscence administration.
- Dynamic Typing:Â Neither language requires you to specify if a variable is anÂ
int
,Âfloat
,Âstring
, and so on. The kinds are checked at runtime. - Object-Oriented Programming: Each languages are object-oriented. Each help lessons, inheritance, polymorphism, and so on. Ruby is extra “pure”, within the sense that actually all the pieces is an object, whereas in Python a couple of issues (corresponding toÂ
if
 andÂfor
 statements) should not objects. - Readable and Concise Syntax: Each are thought-about simple to be taught. Both is nice for a first-time learner.
- Large Ecosystem of Packages:Â Packages to do all types of cool issues can be found in each languages. In Python they’re referred to as libraries, and in Ruby they’re referred to as gems.
The first distinction between the 2 languages lies of their philosophy and design ideas. Python’s core philosophy could be described as:
There needs to be one — and ideally just one — apparent strategy to do one thing.
In concept, this could emphasize simplicity, readability, and readability. Ruby’s philosophy could be described as:
There’s at all times multiple strategy to do one thing. Maximize developer happiness.
This was a shock to me after I converted from Python. Try this straightforward instance emphasizing this philosophical distinction:
# A combat over philosophy: iterating over an array
# Pythonic manner
for i in vary(1, 6):
print(i)
# Ruby manner, possibility 1
(1..5).every do |i|
places i
finish
# Ruby manner, possibility 2
for i in 1..5
places i
finish
# Ruby manner, possibility 3
5.occasions do |i|
places i + 1
finish
# Ruby manner, possibility 4
(1..5).every i
One other distinction between the 2 is syntax fashion. Python primarily makes use of indentation to indicate code blocks, whereas Ruby makes use of do…finish
 or {…}
 blocks. Most embody indentation inside Ruby blocks, however that is solely non-obligatory. Examples of those syntactic variations could be seen within the code proven above.
There are loads of different little variations to be taught. For instance, in Python string interpolation is completed utilizing f-strings:Â f"Whats up, {identify}!"
, whereas in Ruby they’re carried out utilizing hashtags:Â "Whats up, #{identify}!"
. Inside a couple of months, I feel any competent Python programmer can switch their proficiency over to Ruby.
Current AI-based Gems
Regardless of not being within the dialog when discussing AI, Ruby has had some latest developments on this planet of gems. I’ll spotlight a few of the most spectacular latest releases that we’ve been utilizing in our company to construct AI apps:
RubyLLM (link) — Any GitHub repo that will get greater than 2k stars inside a couple of weeks of launch deserves a point out, and RubyLLM is certainly worthy. I’ve used many clunky implementations of LLM suppliers from libraries like LangChain and LlamaIndex, so utilizing RubyLLM was like a breath of contemporary air. As a easy instance, let’s check out a tutorial demonstrating multi-turn conversations:
require 'ruby_llm'
# Create a mannequin and provides it directions
chat = RubyLLM.chat
chat.with_instructions "You're a pleasant Ruby skilled who loves to assist learners."
# Multi-turn dialog
chat.ask "Hello! What does attr_reader do in Ruby?"
# => "Ruby creates a getter technique for every image...
# Stream responses in actual time
chat.ask "May you give me a brief instance?" do |chunk|
print chunk.content material
finish
# => "Positive!
# ```ruby
# class Individual
# attr...
Merely superb. Multi-turn conversations are dealt with routinely for you. Streaming is a breeze. Evaluate this to an identical implementation in LangChain:
from langchain_openai import ChatOpenAI
from langchain_core.schema import SystemMessage, HumanMessage, AIMessage
from langchain_core.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
SYSTEM_PROMPT = "You're a pleasant Ruby skilled who loves to assist learners."
chat = ChatOpenAI(streaming=True, callbacks=[StreamingStdOutCallbackHandler()])
historical past = [SystemMessage(content=SYSTEM_PROMPT)]
def ask(user_text: str) -> None:
"""Stream the reply token-by-token and hold the context in reminiscence."""
historical past.append(HumanMessage(content material=user_text))
# .stream yields message chunks as they arrive
for chunk in chat.stream(historical past):
print(chunk.content material, finish="", flush=True)
print() # newline after the reply
# the ultimate chunk has the complete message content material
historical past.append(AIMessage(content material=chunk.content material))
ask("Hello! What does attr_reader do in Ruby?")
ask("Nice - may you present a brief instance with attr_accessor?")
Yikes. And it’s necessary to notice that this can be a grug implementation. Need to know the way LangChain actually expects you to handle reminiscence? Test out these links, however seize a bucket first; it’s possible you’ll get sick.
Neighbors (link) — This is a wonderful library to make use of for nearest-neighbors search in a Rails software. Very helpful in a RAG setup. It integrates with Postgres, SQLite, MySQL, MariaDB, and extra. It was written by Andrew Kane, the identical man who wrote the pgvector extension that permits Postgres to behave as a vector database.
Async (link) — This gem had its first official launch again in December 2024, and it has been making waves within the Ruby group. Async is a fiber-based framework for Ruby that runs non-blocking I/O duties concurrently whereas letting you write easy, sequential code. Fibers are like mini-threads that every have their very own mini name stack. Whereas not strictly a gem for AI, it has helped us create options like net scrapers that run blazingly quick throughout hundreds of pages. Now we have additionally used it to deal with streaming of chunks from LLMs.
Torch.rb (link) — In case you are thinking about coaching deep studying fashions, then certainly you have got heard of PyTorch. Nicely, PyTorch is constructed on LibTorch, which basically has loads of C/C++ code beneath the hood to carry out ML operations rapidly. Andrew Kane took LibTorch and made a Ruby adapter over it to create Torch.rb, basically a Ruby model of PyTorch. Andrew Kane has been a hero within the Ruby AI world, authoring dozens of ML gems for Ruby.
Abstract
In brief: constructing an internet software with AI integration rapidly and cheaply requires a monolithic structure. A monolith calls for a monolingual software, which is critical in case your finish purpose is high quality apps delivered with velocity. Your primary choices are both Python or Ruby. In case you go together with Python, you’ll in all probability use Django on your net framework. In case you go together with Ruby, you may be utilizing Ruby on Rails. At our company, we discovered Django’s lack of options disappointing. Rails has impressed us with its function set and emphasis on simplicity. We have been thrilled to seek out nearly no points on the AI facet.
In fact, there are occasions the place you’ll not wish to use Ruby. In case you are conducting analysis in AI or coaching machine studying fashions from scratch, then you’ll seemingly wish to follow Python. Analysis nearly by no means includes constructing Web Applications. At most you’ll construct a easy interface or dashboard in a pocket book, however nothing production-ready. You’ll seemingly need the most recent PyTorch updates to make sure your coaching runs rapidly. You could even dive into low-level C/C++ programming to squeeze as a lot efficiency as you’ll be able to out of your {hardware}. Possibly you’ll even attempt your hand at Mojo.
But when your purpose is to combine the most recent LLMs — both open or closed supply — into net functions, then we imagine Ruby to be the far superior possibility. Give it a shot yourselves!
Partially three of this sequence, I’ll dive right into a enjoyable experiment: simply how easy can we make an internet software with AI integration? Keep tuned.
🔥 In case you’d like a customized net software with generative AI integration, go to losangelesaiapps.com