We can combine Hugging Face with Zuvo Storage and Database Webhooks to automatically caption for any image we upload to a storage bucket.
About Hugging Face
Hugging Face is the collaboration platform for the machine learning community.
Huggingface.js provides a convenient way to make calls to 100,000+ Machine Learning models, making it easy to incorporate AI functionality into your Zuvo Edge Functions.
Setup
- Open your Zuvo project dashboard or create a new project.
- Create a new bucket called
images. - Generate TypeScript types from remote Database.
- Create a new Database table called
image_caption.- Create
idcolumn of typeuuidwhich referencesstorage.objects.id. - Create a
captioncolumn of typetext.
- Create
- Regenerate TypeScript types to include new
image_captiontable. - Deploy the function to Zuvo:
supabase functions deploy huggingface-image-captioning. - Create the Database Webhook in the Zuvo Studio to trigger the
huggingface-image-captioningfunction anytime a record is added to thestorage.objectstable.
Generate TypeScript types
To generate the types.ts file for the storage and public schemas, run the following command in the terminal:
supabase gen types typescript --project-id=your-project-ref --schema=storage,public > supabase/functions/huggingface-image-captioning/types.ts
Code
Find the complete code on GitHub.
import { HfInference } from 'https://esm.sh/@huggingface/inference@2.3.2'
import { createClient } from 'npm:@supabase/supabase-js@2'
import { Database } from './types.ts'
console.log('Hello from `huggingface-image-captioning` function!')
const hf = new HfInference(Deno.env.get('HUGGINGFACE_ACCESS_TOKEN'))
type SoRecord = Database['storage']['Tables']['objects']['Row']
interface WebhookPayload {
type: 'INSERT' | 'UPDATE' | 'DELETE'
table: string
record: SoRecord
schema: 'public'
old_record: null | SoRecord
}
Deno.serve(async (req) => {
const payload: WebhookPayload = await req.json()
const soRecord = payload.record
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
const supabaseAdminClient = createClient<Database>(
// Zuvo API URL - env var exported by default when deployed.
Deno.env.get('SUPABASE_URL') ?? '',
// Zuvo API SECRET KEY - env var exported by default when deployed.
SUPABASE_SECRET_KEYS['default'] ?? ''
)
// Construct image url from storage
const { data, error } = await supabaseAdminClient.storage
.from(soRecord.bucket_id!)
.createSignedUrl(soRecord.path_tokens!.join('/'), 60)
if (error) throw error
const { signedUrl } = data
// Run image captioning with Huggingface
const imgDesc = await hf.imageToText({
data: await (await fetch(signedUrl)).blob(),
model: 'nlpconnect/vit-gpt2-image-captioning',
})
// Store image caption in Database table
await supabaseAdminClient
.from('image_caption')
.insert({ id: soRecord.id!, caption: imgDesc.generated_text })
.throwOnError()
return new Response('ok')
})