Example: Curation of AI Training Data

You need to fine tune your in house AI or answer deep stakeholder questions, but you need to filter your business data by content, and fast!

How FEVER Helps

  • Your media content will have a fingerprint associated after FEVER runs.
  • The FEVER system uses those to allow you to tag and create datasets in S3.
  • FEVER accepts a SQL query, and returns as many items as you request in match score order.
  • Typical sorting and filtering options are supported with the underlying database system.

Implementation Guide

  • If you have not already installed FEVER, follow the Quick Start Guide.
  • 1. Use the provided Admin console to query your multimedia items with SQL.
    • a. You can use natural language search to filter or sort by content scoring, using fever_search (cosine distance - lower number is better):
SELECT b.id, b.external_ref,
       e.vec_full <=> fever_search('animal photos') AS distance
FROM embeddings e
JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
ORDER BY distance
LIMIT 200
    • b. You can also deprioritize synthetic, AI generated visual content using the synthetic score system - sort it last, or filter it out entirely:
SELECT b.id, b.external_ref, a.synthetic
FROM as_blobs b
JOIN annotations a ON a.customer_id = b.customer_id AND a.blob_id = b.id
WHERE a.tags @> ARRAY['hero-shot']
ORDER BY a.synthetic ASC NULLS LAST
LIMIT 500
    • c. CV researchers often collate by asset size. Large byte sizes mean original, uncompressed captures, and width x height keeps low-resolution thumbnails out of the training set:
SELECT b.id, b.external_ref, b.byte_size, b.width, b.height
FROM as_blobs b
WHERE b.byte_size >= 5242880
  AND b.width >= 1024
  AND b.height >= 1024
ORDER BY b.byte_size DESC
LIMIT 1000
  • 2. Once your query returns the results that you expect, simply tag the dataset on the bottom of the page.
  • 3. Navigate to the Export tab, and export the dataset to S3 so that your training jobs can pull it. FEVER is NO EGRESS - datasets leave the appliance only via S3, never as a browser download.

Code Starters

import asyncio

import fever_client

SQL = """
SELECT b.id, b.external_ref,
       e.vec_full <=> fever_search('studio product photo on white background') AS distance
FROM embeddings e
JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
ORDER BY distance
LIMIT 200
"""

async def main():
    config = fever_client.Configuration(
        host="https://your-appliance",
        access_token="YOUR_API_KEY",
    )
    async with fever_client.ApiClient(config) as client:
        query = fever_client.QueryApi(client)
        result = await query.query(fever_client.QueryRequest(sql=SQL))
        for row in result.rows:
            print(dict(zip(result.columns, row)))

asyncio.run(main())
import { Configuration, QueryApi } from "fever-client";

const query = new QueryApi(
  new Configuration({
    basePath: "https://your-appliance",
    accessToken: "YOUR_API_KEY",
  })
);

const sql = `
  SELECT b.id, b.external_ref,
         e.vec_full <=> fever_search('studio product photo on white background') AS distance
  FROM embeddings e
  JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
  ORDER BY distance
  LIMIT 200
`;
const result = await query.query({ queryRequest: { sql } });
for (const row of result.rows) {
  console.log(Object.fromEntries(row.map((value, i) => [result.columns[i], value])));
}
package main

import (
	"context"
	"fmt"

	fever "github.com/Lowdown-Labs/fever-clients/clients/go"
)

func main() {
	cfg := fever.NewConfiguration()
	cfg.Servers = fever.ServerConfigurations{{URL: "https://your-appliance"}}
	ctx := context.WithValue(context.Background(), fever.ContextAccessToken, "YOUR_API_KEY")
	client := fever.NewAPIClient(cfg)

	sql := `SELECT b.id, b.external_ref,
	     e.vec_full <=> fever_search('studio product photo on white background') AS distance
	FROM embeddings e
	JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
	ORDER BY distance
	LIMIT 200`
	req := fever.NewQueryRequest(sql)
	result, _, err := client.QueryAPI.Query(ctx).QueryRequest(*req).Execute()
	if err != nil {
		panic(err)
	}
	for _, row := range result.GetRows() {
		fmt.Println(row)
	}
}
require "fever_client"

FeverClient.configure do |config|
  config.scheme = "https"
  config.host = "your-appliance"
  config.access_token = "YOUR_API_KEY"
end

sql = <<~SQL
  SELECT b.id, b.external_ref,
         e.vec_full <=> fever_search('studio product photo on white background') AS distance
  FROM embeddings e
  JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
  ORDER BY distance
  LIMIT 200
SQL
result = FeverClient::QueryApi.new.query(FeverClient::QueryRequest.new(sql: sql))
result.rows.each { |row| puts result.columns.zip(row).to_h }
import com.lowdownlabs.fever.ApiClient;
import com.lowdownlabs.fever.Configuration;
import com.lowdownlabs.fever.api.QueryApi;
import com.lowdownlabs.fever.model.QueryRequest;
import com.lowdownlabs.fever.model.QueryResult;

public class CurateDataset {
    public static void main(String[] args) throws Exception {
        ApiClient client = Configuration.getDefaultApiClient();
        client.setBasePath("https://your-appliance");
        client.setRequestInterceptor(builder ->
            builder.header("Authorization", "Bearer YOUR_API_KEY"));
        QueryApi api = new QueryApi(client);

        String sql = """
            SELECT b.id, b.external_ref,
                   e.vec_full <=> fever_search('studio product photo on white background') AS distance
            FROM embeddings e
            JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
            ORDER BY distance
            LIMIT 200
            """;
        QueryResult result = api.query(new QueryRequest().sql(sql));
        result.getRows().forEach(System.out::println);
    }
}
use fever_client::apis::{configuration::Configuration, query_api};
use fever_client::models::QueryRequest;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration {
        base_path: "https://your-appliance".to_owned(),
        bearer_access_token: Some("YOUR_API_KEY".to_owned()),
        ..Default::default()
    };
    let sql = "SELECT b.id, b.external_ref, \
               e.vec_full <=> fever_search('studio product photo on white background') AS distance \
               FROM embeddings e \
               JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id \
               ORDER BY distance LIMIT 200";
    let result = query_api::query(&config, QueryRequest::new(sql.to_owned())).await?;
    for row in result.rows {
        println!("{row:?}");
    }
    Ok(())
}
<?php
require_once __DIR__ . '/vendor/autoload.php';

use LowdownLabs\Fever\Api\QueryApi;
use LowdownLabs\Fever\Configuration;
use LowdownLabs\Fever\Model\QueryRequest;

$config = (new Configuration())
    ->setHost('https://your-appliance')
    ->setAccessToken('YOUR_API_KEY');
$api = new QueryApi(null, $config);

$sql = "SELECT b.id, b.external_ref,
        e.vec_full <=> fever_search('studio product photo on white background') AS distance
        FROM embeddings e
        JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
        ORDER BY distance LIMIT 200";
$result = $api->query(new QueryRequest(['sql' => $sql]));
foreach ($result->getRows() as $row) {
    echo json_encode(array_combine($result->getColumns(), $row)) . PHP_EOL;
}
using LowdownLabs.Fever.Api;
using LowdownLabs.Fever.Client;
using LowdownLabs.Fever.Model;

var config = new Configuration
{
    BasePath = "https://your-appliance",
    AccessToken = "YOUR_API_KEY"
};
var api = new QueryApi(config);
var sql = """
    SELECT b.id, b.external_ref,
           e.vec_full <=> fever_search('studio product photo on white background') AS distance
    FROM embeddings e
    JOIN as_blobs b ON b.id = e.blob_id AND b.customer_id = e.customer_id
    ORDER BY distance
    LIMIT 200
    """;
var result = await api.QueryAsync(new QueryRequest(sql: sql));
foreach (var row in result.Rows)
{
    Console.WriteLine(string.Join(", ", row));
}