How to build an AI Product (7) - Build an MVP UI for your backend service

When paired with the robust FastAPI framework, a tool like jQuery can be instrumental in achieving this. FastAPI, known for its high performance and Pythonic ease, serves as an optimal backend choice for modern web applications.

To serve an HTML page from a FastAPI service and integrate it with the /similar/ endpoint using jQuery, you can follow these steps:

  1. Create an endpoint in FastAPI to serve the HTML content.
  2. Create the HTML content with a form that accepts the user input and a button to trigger the AJAX request using jQuery.
  3. Update the jQuery code to handle the AJAX request and display the results.

Here's how you can accomplish this:

Update FastAPI Service

First, modify your FastAPI service to serve an HTML page:

from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from starlette.requests import Request
from typing import List, Dict
from annoy import AnnoyIndex
import numpy as np
from sentence_transformers import SentenceTransformer

# ... [rest of your existing imports and initialization code]

app = FastAPI()

# Mount static files directory for serving css, js, etc.
app.mount("/static", StaticFiles(directory="static"), name="static")

# Setting up the Jinja2 templates directory
templates = Jinja2Templates(directory="templates")

@app.get("/")
def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

# ... [rest of your existing code]

The final main.py looks like the following;

from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from starlette.requests import Request

from typing import List
from annoy import AnnoyIndex
import numpy as np
from sentence_transformers import SentenceTransformer
import os
from typing import Dict



app = FastAPI()

# Mount static files directory for serving css, js, etc.
app.mount("/static", StaticFiles(directory="static"), name="static")

# Setting up the Jinja2 templates directory
templates = Jinja2Templates(directory="templates")

@app.get("/")
def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})
# Initializing the model
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')



# Number of dimensions should be specific to the embeddings model used when creating the index.
t = AnnoyIndex(384, 'angular')

# Load the pre-built Annoy index
t.load('text_embeddings_index.ann')

# Create a function to convert text to embedding. This will be used to encode the input text.
def text_to_vector(text: str) -> np.array:
    print(text)
    return model.encode(text)


@app.get("/similar/")
def get_similar_sentences(sentence: str, num_results: int = 5) -> Dict[str, str]:
    # Convert the input sentence to a vector
    vector = text_to_vector(sentence)
    
    # Query the Annoy index for the most similar vectors
    indices = t.get_nns_by_vector(vector, num_results)
    
    # For simplicity, we're returning the indices of the most similar sentences.
    # In practice, you might want to map these indices back to the actual sentences or data.
    
    return {"similar_indices": '|'.join([str(k) for k in indices])}
    

Create the HTML content

Create a directory named templates in the same directory as your FastAPI app. Inside templates, create a file named index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Find Similar Sentences</title>
    <link rel="stylesheet" href="/static/style.css">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <div class="container">
        <h1>Enter your sentence</h1>
        <input type="text" id="sentence" placeholder="Type a sentence...">
        <button id="submit">Find Similar</button>
        <h2>Similar Indices:</h2>
        <p id="results"></p>
    </div>
    <script src="/static/script.js"></script>
</body>
</html>

Create the jQuery Code

Create a directory named static in the same directory as your FastAPI app. Inside static, create a file named script.js:

$(document).ready(function(){
    $("#submit").click(function(){
        var sentence = $("#sentence").val();
        $.get(`/similar/?sentence=${sentence}`, function(data){
            $("#results").text(data.similar_indices);
        });
    });
});

Add Some CSS (optional)

Still in the static directory, create a file named style.css:

.container {
    max-width: 600px;
    margin: 50px auto;
    text-align: center;
}

input {
    padding: 10px;
    width: 80%;
    margin-bottom: 10px;
}

button {
    padding: 10px 15px;
    background-color: #007BFF;
    border: none;
    color: #fff;
    cursor: pointer;
}

h2 {
    margin-top: 20px;
}

When you run your FastAPI service and go to the root URL (e.g., http://0.0.0.0:3000/), you will see an input field.

After you input a sentence and click the "Find Similar" button, the similar sentence indices will be displayed below.

The folder structure is very simple, in case you were wondering.

You can now continue building more UI/UX elements.

Conclusion

With the foundational setup in place, users are now well-equipped to further enhance and refine the user interface and experience of their FastAPI service. Leveraging jQuery, they can easily integrate dynamic behaviors, animations, and asynchronous server calls, enriching the interactive elements of the service.

Moreover, by incorporating TailwindCSS, a utility-first CSS framework, users can rapidly prototype and style their UI components with minimal effort, while maintaining a clean and modern design.

The combination of jQuery for interactivity and TailwindCSS for styling provides a robust toolkit to create responsive, user-friendly, and aesthetically pleasing web applications.

As the needs of the service grow, these tools can be incrementally expanded upon, allowing for a scalable and adaptable UI/UX development process.

🤖 Want to Build the Next Big AI Product?

Join our hands-on, real-life bootcamp and transform your ideas into groundbreaking AI solutions.

Sign Up Now