How to Build an Instant Vector Search App using Hypermode & Modus

A step-by-step walkthrough guide to creating vector search from scratch

Discover how to create a robust instant vector search application using Hypermode and Modus
Discover how to create a robust instant vector search application using Hypermode and Modus

This guide will walk you through creating a basic instant vector search project using Hypermode and Modus, Hypermode’s serverless framework. You’ll learn how to configure AI models, set up collections for your data, and deploy search functions — all with minimal setup.

Watch a video walkthrough here or follow the written step-by-step guide below (with all of the code examples taken from this GitHub repo):

Hypermode is a managed service that provides the infrastructure and tools for creating AI-powered applications, including assistants, APIs, and backend services. It offers:

  • Automatic building and deployment of functions with each git push

  • A live, scalable API for previewing, testing, and production

  • Access to various AI models for experimentation

  • Integrated console for observability and control

Modus is an open-source, serverless framework that’s part of the Hypermode ecosystem. It focuses on:

  • GraphQL API generation for easy integration

  • Building functions and APIs using WebAssembly

  • Supporting multiple programming languages (currently Go and AssemblyScript — a TypeScript-like language that compiles to WebAssembly)

  • Providing features to integrate models, data, and external services

  • Scaling from simple CRUD operations to complex AI systems

What Is Vector Search?

Instant vector search allows you to find semantically similar items by comparing their vector representations, also known as embeddings. Embeddings are numerical representations of text that help the AI understand the meaning of words and compare them based on similarity.

Performing a semantic search typically involves multiple steps and can take over two seconds, making it impractical for real-time applications. With Hypermode, that search time is streamlined to under 200 milliseconds for the end user — which includes important backend steps like embedding and more. This advancement makes real-time vector search practical and efficient for a wide range of use cases.

Traditionally, setting up vector search required managing AI models, embeddings, and data indexing, which can be complex. Hypermode simplifies this by allowing you to quickly add vector search to your application with easy configurations for models and data collections.

By the end of this guide, you’ll have a fully functional vector search system up and running, ready to be customized to your specific needs.

Find all the code used this project here on this GitHub repo.

Setting up Your Project

To get started, we'll need to install Modus. Make sure you have Node.js v22 or higher installed on your machine.

  1. Install the Modus CLI

    First, you need to install the Modus CLI, which provides commands for creating, building, and running your app. Open a terminal and run the following command:

    npm install -g

    This installs the CLI globally, so you can access it from any directory.


  2. Initialize Your Modus App

    Create a new Modus project by running the following command in your terminal:

    You’ll be prompted to name your project and choose a programming language for your app. You can select either Go or AssemblyScript based on your preference. For this example, we’ll use AssemblyScript.

    Next, you’ll be asked to choose a template – select default to follow along with this guide. Once completed, the command will generate a new directory containing all the essential files and folders to get started.


  3. Project Structure Overview

    A Modus app comes with a pre-configured structure. Here are the key files and directories:

    • /assembly/: Where you’ll create custom functions, such as those for vector search.

    • modus.json: The app manifest where you define connections to external services and configure your app.


  4. Build & Run Your App

    To build and run your app, navigate to the app directory and run the following command:

    modus dev

    This command runs your app locally in a development mode and provides you with a URL to access your app’s generated API.


💡 Note: To use collections locally, you’ll need to set up a PostgreSQL database. Follow the instructions here to configure PostgreSQL for working with collections.

Now that you have your Modus app set up, you’re ready to start configuring AI models and building out your vector search functionality.

Using the Modus SDK

The Modus SDK is a powerful toolkit for building and deploying AI-powered applications. It simplifies the process of creating AI-driven systems by providing everything you need to manage functions, handle data, and interact with AI models. Here's an overview of its key features:

  1. Multi-Language Support: The SDK currently supports Go and AssemblyScript, with additional language support in development. This allows you to write functions in your preferred language.


  2. Auto-Generated API: A secure API is automatically generated from your function signatures, making it easy to expose your functions as endpoints.


  3. Model Integration: The SDK allows you to connect and invoke AI models from different providers without learning a new SDK for each one. The Models API provides a flexible way to interact with various AI models directly from your functions.


  4. Database Integration: The SDK offers simple ways to interact with databases, such as PostgreSQL, through dedicated APIs.


  5. Search Capabilities: You can add natural language search and recommendations with integrated vector embeddings.


  6. Authentication: Secure your API endpoints with minimal configuration.


  7. WebAssembly Runtime: The SDK uses a small and portable execution engine for deployment across server, edge, and desktop computes.


  8. HTTP API Integration: The SDK provides a secure way to call and fetch data from HTTP endpoints, similar to the JavaScript fetch API but with some modifications for Hypermode Functions.


  9. App Manifest: The modus.json file serves as the central configuration for your Modus app, defining endpoints, connections, models, and collections available during runtime.


  10. Local Development: The Modus SDK supports local development, allowing you to build and run your Modus app on your local machine, allowing for rapid experimentation.


  11. Logging: The Console API is globally available in all functions, allowing developers to capture log messages and errors that are automatically included in Modus runtime execution logs.

To start using the Modus SDK in your project, you can import the necessary APIs like this:

import { http, collections, models } from "@hypermode/modus-sdk";

This setup makes it easy to experiment with AI features, interact with databases, and make HTTP requests. As your project evolves, you can quickly update your configuration to try out new models or adjust your functions as needed.

Setting up the Modus Manifest

Now that we understand how the SDK works, let's configure the Modus manifest. The modus.json file is where we configure the AI models and collections that power your vector search project. This manifest defines how your application interacts with AI models and organizes data for searching.

AI Models

To perform vector search, we need an AI model that generates vector embeddings from text data. For this guide, we'll use the sentence-transformers/all-MiniLM-L6-v2 model from Hugging Face, which is lightweight and efficient for embedding product names and descriptions.

To add the model to your project, update the modus.json file like this:

"models": {
  "minilm": {
    "sourceModel": "sentence-transformers/all-MiniLM-L6-v2",
    "provider": "hugging-face",
    "connection": "hypermode"
  }
}
  • sourceModel: Specifies the AI model to be used, in this case, sentence-transformers/all-MiniLM-L6-v2.

  • provider: Indicates the source of the model. In this example, it’s Hugging Face.

  • connection: Specifies the model will be hosted on Hypermode.

This model will generate the vector embeddings that your search functions will use to return relevant results.

Collections

Next, we need to configure our collections. Collections are built-in key-value storage systems with support for vector embeddings, enabling natural language search capabilities within your functions. For this project, we’ll define only one collection: texts for storing the texts we want to search through.

Here’s how to configure the collections in the modus.json file:

  "collections": {
    "texts": {
      "searchMethods": {
        "searchMethod1": {
          "embedder": "miniLMEmbed",
          "index": {
            "type": "sequential"
          }
        }
      }
    }
  }

This collection stores text and has search methods configured. These settings define how searches will be performed on the collection. In this case, we connect the collection to the miniLMEmbed function, which generates vector embeddings for the product names, enabling similarity-based searches. We’ll cover how to create the miniLMEmbed function later in this guide.

By defining the AI models and collections in the hypermode.json file, we enable your application to perform powerful vector searches with minimal configuration.

Writing Your Functions

Now that we've set up our models and collections, it's time to write the core functions that will handle embedding product data and performing semantic search. Modus supports functions written in either AssemblyScript or Go, and these need to follow specific guidelines to work correctly.

  • Choosing Your Programming Language:

    • If you selected AssemblyScript, navigate to the /functions/assembly/index.ts file.

    • If you chose Go, navigate to the /functions/go/index.go file.

    • These are the files from which your functions will be exported and made accessible as API endpoints.


  • Clean Up Existing Functions: Delete any template functions to start fresh with your own logic. This keeps your project clean and focused on your specific use case.


  • Understanding Modus Functions:

    • AssemblyScript: This is a TypeScript-like language that compiles to WebAssembly, providing better performance and a lightweight runtime.

    • Go: If you prefer Go, you can build your functions using its robust, concurrent features.

    • Exporting Functions: To expose your functions as API endpoints, you need to explicitly export them from the appropriate index file (either index.ts or index.go). Modus will automatically generate an API for all exported functions, making them available externally.


  • Modus API Generation: Modus automates the creation of APIs from exported functions. Once your functions are properly exported, they will be deployed and accessible through the generated API endpoints, simplifying the process of building and scaling your application.

Let’s walk through the key functions that will power the product vector search. First, we need to import the following modules and types.

import { collections } from "@hypermode/modus-sdk-as";
import { models } from "@hypermode/modus-sdk-as";
import { EmbeddingsModel } from "@hypermode/modus-sdk-as/models/experimental/embeddings";
  • collections: This allows you to interact with the collections for storing and retrieving texts and other relevant data

  • models: This is where we access AI models for embedding generation. Specifically, we’ll use the EmbeddingsModel, which allows us to convert product names and descriptions into vector embeddings for similarity-based search.

  • EmbeddingsModel: Imported from @hypermode/modus-sdk-as/models/experimental/embeddings, this model is responsible for generating vector embeddings from text data. These embeddings capture the semantic meaning of product names and descriptions, enabling powerful, real-time vector searches.

Next, we need to define key parameters for interacting with the Hypermode environment:

const textsCollection = "texts";
const searchMethod = "searchMethod1";
const embeddingModelName = "minilm";
  • textsCollection: Specifies the name of the collection where the text data is stored.

  • searchMethod: Defines the search algorithm to use (in this case, searchMethod1).

  • embeddingModelName: Indicates the AI model (minilm) responsible for generating vector embeddings from the text.

These values will be used throughout the template to configure how we store, retrieve, and search through text data.

The upsertTexts Function

The upsertTexts function is responsible for inserting or updating text data in the texts collection. This is crucial for maintaining up-to-date content in your vector search system, as it allows you to add new texts or update existing entries.

export function upsertTexts(ids: string[], texts: string[]): string[] {
  const errors: string[] = [];

  if (ids.length !== texts.length) {
    errors.push("Length of all arrays must be the same");
    return errors;
  }

  let result = collections.upsertBatch(textsCollection, ids, texts);

  if (!result.isSuccessful) {
    errors.push(result.error);
    return errors;
  }

  return ids;
}
  • Parameters:

    • ids: An array of unique identifiers for the texts.

    • texts: An array of text content corresponding to each ID.


  • Process:

    1. Validation: It checks whether the ids and texts arrays are the same length to prevent mismatched data.

    2. Batch Upsert: It uses collections.upsertBatch to insert or update the texts in the textsCollection.

    3. Error Handling: If the upsert fails, it collects and returns error messages; otherwise, it returns the array of IDs indicating successful upsert.

The search Function

The search function performs a semantic search on the texts collection, returning the text entries most similar to the user’s search query. This function is the core of the vector search feature, enabling users to find relevant text data based on their query.

export function search(query: string): string[] {
  const searchResults = collections.search(
    textsCollection,
    searchMethod,
    query,
    10,
    true,
  );

  if (!searchResults.isSuccessful) {
    return [searchResults.error];
  }
  const searchTexts: string[] = [];

  for (let i = 0; i < searchResults.objects.length; i++) {
    const obj = searchResults.objects[i];
    const text = collections.getText(textsCollection, obj.key);
    if (text) {
      searchTexts.push(text);
    }
  }
  return searchTexts;
}
  • Parameters:

    • query: The search string provided by the user.


  • Process:

    1. Search Execution: It performs a vector-based semantic search using the collections.search method on the textsCollection, with the provided query and specified search method.

    2. Result Handling: If the search is successful, it loops through the search results, retrieving the corresponding text for each result from the collection using collections.getText.

    3. Return: The function returns an array of the most relevant texts based on the search query.

This function is essential for leveraging Hypermode’s vector search capabilities, allowing you to efficiently retrieve relevant text data based on semantic similarity.

The miniLMEmbed Function

This function generates vector embeddings from an array of text strings. It is crucial for converting text into vector representations that can be used for semantic search.

export function miniLMEmbed(texts: string[]): f32[][] {
  const model = models.getModel<EmbeddingsModel>(consts.embeddingModelName);
  const input = model.createInput(texts);
  const output = model.invoke(input);

  return output.predictions;
}
  • Parameters:

    • texts: Array of strings to be embedded.

  • Process:

    1. It retrieves the miniLMEmbed model.


    2. It prepares the input (the array of texts) and invokes the model.


    3. The model returns embeddings (vectors) for the texts, which are used in the vector search.

By adding these, you’ve written the core functions needed for embedding text data and performing vector-based searches using Hypermode. The upsertTexts function allows you to add or update text entries, and the search function performs the semantic search based on user queries. The miniLMEmbed function generates the embeddings necessary for powering the search functionality.

Once you’ve implemented these functions, you can deploy them to Hypermode and start testing real-time vector search capabilities with your own text data.

Deploying & Testing Your Instant Vector Search App

Now that you've created and built an app with Modus and have it running locally, here’s how you can deploy, test, and iterate your app with Hypermode:

1. Import Your Modus App into Hypermode

You have two ways to import your app:

  1. Via the Hypermode Console:

    • Navigate to the Hypermode Console and click "New Project."

    • Connect your GitHub account and select your repository.

    • Click "Import" to deploy your app.


  2. Via Hyp CLI:

    • Install the Hyp CLI:

      npm install -g


    • Run the following command in your terminal to initialize and deploy your app:

2. Upload Data to Your Collections

To use your vector search app, upload data to the texts collection. You have two options:

  • CSV Upload via the Hypermode Console: Use the dashboard to upload a CSV file.

  • Programmatically using the upsertTexts Function: Call the upsertTexts function you created to upload data directly.

3. Test Your API Endpoints

After deployment, your functions are available as GraphQL endpoints. Use the Query page in the Hypermode Console to test them. Here’s an example query:


4. Explore Function Execution

  • Use the Inferences page to view step-by-step execution details for each function.

  • Check inputs, outputs, and performance metrics to monitor and optimize your app’s behavior.

5. Iterate & Customize

Hypermode follows a git-based deployment flow. Whenever you push changes to your connected GitHub repository:

  1. Hypermode automatically builds and redeploys your app.

  2. You can view the updated API endpoints and function statuses in the Console.

Try modifying a function, such as generateText, push your changes, and see the updates reflected immediately.

Conclusion

Congratulations! You’ve successfully created an instant vector search application using Hypermode and Modus.

With your setup complete, you now have a solid foundation to build and deploy AI-powered search functionality that can be tailored to various use cases. Go ahead and customize your setup further to fit your specific needs!


Ready to reimagine what you can build? Sign up for a free Hypermode account and use Modus to start building intelligent APIs that integrate models, data, and business logic into blazingly-fast serverless apps.

>> Sign Me Up

Stay updated

Hypermode Inc. © 2024

Stay updated

Hypermode Inc. © 2024

Stay updated

Hypermode Inc. © 2024