Skip to main content

Build an image search engine in under 100 lines of JavaScript

ยท 3 min read

Let's build a simple image search engine, which allows you to search for images using text. We'll use SvectorDB to create and query our embeddings.

Setup

Create a new folder and run the following commands:

npm init -y
npm install @svector/client

Next, let's create a new file called index.ts and add the following code:

import { DatabaseService, EmbeddingModel } from '@svector/client';

const region = 'us-east-2';
const apiKey = ''; // replace with your API key
const databaseId = ''; // replace with your database ID

const client = new DatabaseService({
endpoint: `https://${region}.api.svectordb.com`,
apiKey: apiKey,
});

Create a new database

Let's create a new database to store our image embeddings. You'll need to sign up for a free account at SvectorDB and create a database with 512 dimensions. Once you've created the database, copy the API key and database ID into the above code.

For help on creating a new database, check out the quick start guide.

Add images to the database

Next, let's add some images to the database. We'll use SvectorDB's built-in support for OpenAI's CLIP model to generate embeddings for the images. This model can generate embeddings for both text and images, allowing us to search for images using text.

const imagePath = `./image/apple-1.jpg`;
const imageBuffer = readFileSync(imagePath);

const { vector } = await client.embed({
databaseId,
model: EmbeddingModel.CLIP_VIT_BASE_PATH32,
input: {
image: imageBuffer,
}
})

await client.setItem({
databaseId,
key: 'apple-1',
value: Buffer.from(imagePath),
vector: vector,
})

In the above code, we're loading an image from the file system and generating an embedding using the CLIP model. We then store the image embedding in the database with the key apple-1. Each item in the database should have a unique key, otherwise, it will be treated as an update. Repeat this for each image you want to add to the database.

Search for images

Embeddings locate similar items close together, e.g. the apples will be close together in space but far from bananas. We can use the distance between embeddings to find the nearest images to our query.

OpenAI's CLIP model can generate embeddings for both text and images, so we can search for images by finding the nearest embeddings to our text query. For example, if we search for "Green apples", the nearest images will be those of green apples.

const searchQuery = `Green apples`;

const { vector } = await client.embed({
databaseId,
model: EmbeddingModel.CLIP_VIT_BASE_PATH32,
input: {
text: searchQuery,
},
});

const { results } = await client.query({
databaseId,
query: {
vector: vector!,
},
maxResults: 5
})

With our nearest images found, we can now load them and pass them to the front-end with their scores:

const pictures = results!
.map(({distance, value}) => ({
score: distance,
image: readFileSync(value!.toString())
}));

Ready to experience the difference?

No credit card required