{
"apiVersion": "zebflow.com/v1",
"kind": "Pipeline",
"metadata": {
"name": "openai-embed"
},
"spec": {
"id": "openai-embed",
"nodes": [
{
"id": "trigger",
"kind": "trigger.function",
"config": {
"description": "Embeds one text or a list of texts with the chosen provider's embedding model."
},
"input_pins": [],
"output_pins": [
"out"
]
},
{
"id": "prepare",
"kind": "javascript.script.run",
"config": {
"source": "var a = input.function; var p = ctx.placeholder || {}; var text = [].concat(a.text === undefined || a.text === null ? [] : a.text); text = [].concat.apply([], text).map(function (t) { return t === null || t === undefined ? '' : String(t); }); if (text.length === 0 || text.some(function (t) { return t.trim() === ''; })) throw new Error('--text is empty; it needs the text to embed'); if (text.length > 2048) throw new Error('--text gives ' + text.length + ' texts; at most 2048 are embedded at once'); var model = a.model || p.MODEL || (a.provider === 'openrouter' ? 'openai/text-embedding-3-small' : 'text-embedding-3-small'); return { model: String(model), input: text };"
},
"input_pins": [
"in"
],
"output_pins": [
"out"
]
},
{
"id": "call",
"kind": "http.response.fetch",
"config": {
"method": "POST",
"url": "{{ ($placeholder.BASE_URL || (input.function.provider === 'openrouter' ? 'https://openrouter.ai/api/v1' : 'https://api.openai.com/v1')).replace(/\\/$/, '') }}{{ $placeholder.EMBEDDING_PATH || '/embeddings' }}",
"headers": {
"Authorization": "Bearer {{ $placeholder.API_KEY }}",
"Content-Type": "application/json"
},
"body": "{{ input.script }}",
"timeout": "2m"
},
"input_pins": [
"in"
],
"output_pins": [
"out"
]
},
{
"id": "answer",
"kind": "javascript.script.run",
"config": {
"source": "var r = input.response || {}; var b = r.body || {}; if (!r.ok || !Array.isArray(b.data)) throw new Error('the provider answered no embeddings: ' + (b.error ? (b.error.message || JSON.stringify(b.error)) : ('HTTP ' + r.status))); var vectors = b.data.slice().sort(function (x, y) { return (x.index || 0) - (y.index || 0); }).map(function (d) { return d.embedding; }); return { vectors: vectors, model: b.model, dims: vectors.length ? vectors[0].length : 0, usage: b.usage || null };"
},
"input_pins": [
"in"
],
"output_pins": [
"out"
]
}
],
"edges": [
{
"from_node": "trigger",
"from_pin": "out",
"to_node": "prepare",
"to_pin": "in"
},
{
"from_node": "prepare",
"from_pin": "out",
"to_node": "call",
"to_pin": "in"
},
{
"from_node": "call",
"from_pin": "out",
"to_node": "answer",
"to_pin": "in"
}
]
}
}