chub-dev 0.1.0 → 0.1.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: model-hosting
|
|
3
|
+
description: "Replicate JavaScript SDK coding guide for running ML models via the official Replicate npm package"
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "javascript"
|
|
6
|
+
versions: "1.3.1"
|
|
7
|
+
updated-on: "2026-03-02"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "replicate,model-hosting,ml,inference,ai"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Replicate JavaScript SDK Coding Guide
|
|
13
|
+
|
|
14
|
+
## 1. Golden Rule
|
|
15
|
+
|
|
16
|
+
**Always use the official Replicate SDK package:** `replicate` from npm. The GitHub repository is `replicate/replicate-javascript`.
|
|
17
|
+
|
|
18
|
+
**Never use unofficial or deprecated libraries.** The `replicate` package is the only officially supported Node.js/JavaScript SDK maintained by Replicate. Do not use packages like `replicate-api` or other third-party alternatives.
|
|
19
|
+
|
|
20
|
+
**Important version note:** This SDK requires Node.js 18 or later, as it uses the native `fetch` API available in modern Node.js environments.
|
|
21
|
+
|
|
22
|
+
## 2. Installation
|
|
23
|
+
|
|
24
|
+
### npm
|
|
25
|
+
```bash
|
|
26
|
+
npm install replicate
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### yarn
|
|
30
|
+
```bash
|
|
31
|
+
yarn add replicate
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### pnpm
|
|
35
|
+
```bash
|
|
36
|
+
pnpm add replicate
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Environment Variables (Required):**
|
|
40
|
+
```bash
|
|
41
|
+
REPLICATE_API_TOKEN=r8_your_api_token_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Optional Environment Variables:**
|
|
45
|
+
```bash
|
|
46
|
+
REPLICATE_API_BASE_URL=https://api.replicate.com/v1 # Custom API endpoint
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Security Best Practices:** Never hardcode API tokens in source code. Use environment variables or secure secret management services. Use different tokens for development, staging, and production. Refresh tokens periodically. Never commit tokens to version control. Replicate automatically scans GitHub for accidentally committed tokens and disables them.
|
|
50
|
+
|
|
51
|
+
## 3. Initialization
|
|
52
|
+
|
|
53
|
+
### Basic Initialization
|
|
54
|
+
```javascript
|
|
55
|
+
import Replicate from "replicate";
|
|
56
|
+
|
|
57
|
+
const replicate = new Replicate({
|
|
58
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Custom Configuration
|
|
63
|
+
```javascript
|
|
64
|
+
import Replicate from "replicate";
|
|
65
|
+
|
|
66
|
+
const replicate = new Replicate({
|
|
67
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
68
|
+
userAgent: "my-app/1.0.0",
|
|
69
|
+
baseUrl: "https://api.replicate.com/v1",
|
|
70
|
+
fetch: customFetch, // Custom fetch implementation
|
|
71
|
+
fileEncodingStrategy: "upload", // "upload" or "no-upload"
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### TypeScript Usage
|
|
76
|
+
```typescript
|
|
77
|
+
import Replicate from "replicate";
|
|
78
|
+
import type { Prediction, Model, Training } from "replicate";
|
|
79
|
+
|
|
80
|
+
const replicate = new Replicate({
|
|
81
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**File Encoding Strategy:** `"upload"` (default) automatically uploads file handles to Replicate's file storage. `"no-upload"` does not upload files and is useful when you want to manage file uploads manually.
|
|
86
|
+
|
|
87
|
+
## 4. Core API Surfaces
|
|
88
|
+
|
|
89
|
+
### Running Models with `replicate.run()`
|
|
90
|
+
|
|
91
|
+
**Minimal Example:**
|
|
92
|
+
```javascript
|
|
93
|
+
const output = await replicate.run(
|
|
94
|
+
"black-forest-labs/flux-schnell",
|
|
95
|
+
{
|
|
96
|
+
input: {
|
|
97
|
+
prompt: "a 19th century portrait of a raccoon gentleman wearing a suit"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
console.log(output);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Advanced Example with Version and Options:**
|
|
106
|
+
```javascript
|
|
107
|
+
const output = await replicate.run(
|
|
108
|
+
"stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
109
|
+
{
|
|
110
|
+
input: {
|
|
111
|
+
prompt: "a futuristic cityscape at sunset",
|
|
112
|
+
negative_prompt: "blurry, low quality",
|
|
113
|
+
num_inference_steps: 50,
|
|
114
|
+
guidance_scale: 7.5,
|
|
115
|
+
width: 1024,
|
|
116
|
+
height: 1024,
|
|
117
|
+
seed: 42
|
|
118
|
+
},
|
|
119
|
+
wait: {
|
|
120
|
+
mode: "block", // "block" or "poll"
|
|
121
|
+
interval: 500, // Polling interval in ms (default 500)
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
(progress) => {
|
|
125
|
+
console.log("Progress:", progress);
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Identifier Formats:**
|
|
131
|
+
|
|
132
|
+
The identifier parameter accepts three formats:
|
|
133
|
+
|
|
134
|
+
1. **Model name only** (uses latest version):
|
|
135
|
+
```javascript
|
|
136
|
+
"black-forest-labs/flux-schnell"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
2. **Model name with version**:
|
|
140
|
+
```javascript
|
|
141
|
+
"stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
3. **Version ID only**:
|
|
145
|
+
```javascript
|
|
146
|
+
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Progress Callback:**
|
|
150
|
+
```javascript
|
|
151
|
+
const output = await replicate.run(
|
|
152
|
+
"meta/llama-2-70b-chat",
|
|
153
|
+
{
|
|
154
|
+
input: {
|
|
155
|
+
prompt: "Write a story about a brave knight"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
(prediction) => {
|
|
159
|
+
console.log("Status:", prediction.status);
|
|
160
|
+
if (prediction.output) {
|
|
161
|
+
console.log("Partial output:", prediction.output);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Streaming Output with `replicate.stream()`
|
|
168
|
+
|
|
169
|
+
**Minimal Streaming Example:**
|
|
170
|
+
```javascript
|
|
171
|
+
for await (const event of replicate.stream(
|
|
172
|
+
"meta/llama-2-70b-chat",
|
|
173
|
+
{
|
|
174
|
+
input: {
|
|
175
|
+
prompt: "Tell me a story about a dragon"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
)) {
|
|
179
|
+
process.stdout.write(event.toString());
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Advanced Streaming with Event Handling:**
|
|
184
|
+
```javascript
|
|
185
|
+
const stream = await replicate.stream(
|
|
186
|
+
"meta/llama-2-70b-chat",
|
|
187
|
+
{
|
|
188
|
+
input: {
|
|
189
|
+
prompt: "Explain quantum computing",
|
|
190
|
+
max_new_tokens: 500,
|
|
191
|
+
temperature: 0.7
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
let fullOutput = "";
|
|
197
|
+
|
|
198
|
+
for await (const event of stream) {
|
|
199
|
+
if (event.event === "output") {
|
|
200
|
+
fullOutput += event.data;
|
|
201
|
+
process.stdout.write(event.data);
|
|
202
|
+
} else if (event.event === "error") {
|
|
203
|
+
console.error("Error:", event.data);
|
|
204
|
+
} else if (event.event === "done") {
|
|
205
|
+
console.log("\nGeneration complete");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.log("\nFull output:", fullOutput);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Streaming with EventSource (Server-Sent Events):**
|
|
213
|
+
```javascript
|
|
214
|
+
import Replicate from "replicate";
|
|
215
|
+
|
|
216
|
+
const replicate = new Replicate({
|
|
217
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Create a prediction with streaming enabled
|
|
221
|
+
const prediction = await replicate.predictions.create({
|
|
222
|
+
version: "2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1",
|
|
223
|
+
input: {
|
|
224
|
+
prompt: "Tell me a story"
|
|
225
|
+
},
|
|
226
|
+
stream: true,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// For browser environments
|
|
230
|
+
if (typeof EventSource !== 'undefined') {
|
|
231
|
+
const source = new EventSource(prediction.urls.stream, {
|
|
232
|
+
withCredentials: true,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
source.addEventListener("output", (e) => {
|
|
236
|
+
console.log("Output:", e.data);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
source.addEventListener("error", (e) => {
|
|
240
|
+
console.error("Error:", JSON.parse(e.data));
|
|
241
|
+
source.close();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
source.addEventListener("done", (e) => {
|
|
245
|
+
console.log("Done:", JSON.parse(e.data));
|
|
246
|
+
source.close();
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Predictions API
|
|
252
|
+
|
|
253
|
+
**Create a Prediction:**
|
|
254
|
+
```javascript
|
|
255
|
+
const prediction = await replicate.predictions.create({
|
|
256
|
+
version: "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
257
|
+
input: {
|
|
258
|
+
prompt: "a beautiful landscape"
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
console.log(prediction.id);
|
|
263
|
+
console.log(prediction.status); // "starting"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Advanced Prediction with All Options:**
|
|
267
|
+
```javascript
|
|
268
|
+
const prediction = await replicate.predictions.create({
|
|
269
|
+
version: "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
270
|
+
input: {
|
|
271
|
+
prompt: "astronaut riding a horse on mars",
|
|
272
|
+
width: 1024,
|
|
273
|
+
height: 1024,
|
|
274
|
+
num_inference_steps: 50
|
|
275
|
+
},
|
|
276
|
+
webhook: "https://api.myapp.com/webhooks/replicate",
|
|
277
|
+
webhook_events_filter: ["start", "output", "logs", "completed"],
|
|
278
|
+
stream: false,
|
|
279
|
+
wait: {
|
|
280
|
+
mode: "poll",
|
|
281
|
+
interval: 500
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Get Prediction Status:**
|
|
287
|
+
```javascript
|
|
288
|
+
const prediction = await replicate.predictions.get("gm3qorzdhgbfurvjtvhg6dckhu");
|
|
289
|
+
|
|
290
|
+
console.log(prediction.status); // "succeeded", "processing", "failed", "canceled"
|
|
291
|
+
console.log(prediction.output);
|
|
292
|
+
console.log(prediction.logs);
|
|
293
|
+
console.log(prediction.metrics);
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Wait for Prediction to Complete:**
|
|
297
|
+
```javascript
|
|
298
|
+
let prediction = await replicate.predictions.create({
|
|
299
|
+
version: "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
300
|
+
input: { prompt: "a serene lake" }
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Poll until completion
|
|
304
|
+
prediction = await replicate.wait(prediction);
|
|
305
|
+
|
|
306
|
+
console.log(prediction.status); // "succeeded" or "failed"
|
|
307
|
+
console.log(prediction.output);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Cancel a Prediction:**
|
|
311
|
+
```javascript
|
|
312
|
+
const canceled = await replicate.predictions.cancel("gm3qorzdhgbfurvjtvhg6dckhu");
|
|
313
|
+
|
|
314
|
+
console.log(canceled.status); // "canceled"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Important:** If you cancel a prediction before it starts, there's no charge. If you cancel after it starts, you're billed for the time used.
|
|
318
|
+
|
|
319
|
+
**List Predictions:**
|
|
320
|
+
```javascript
|
|
321
|
+
// Automatic pagination
|
|
322
|
+
for await (const prediction of replicate.predictions.list()) {
|
|
323
|
+
console.log(prediction.id, prediction.status);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Manual pagination
|
|
327
|
+
let page = await replicate.predictions.list();
|
|
328
|
+
for (const prediction of page.results) {
|
|
329
|
+
console.log(prediction.id);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
while (page.next) {
|
|
333
|
+
page = await replicate.predictions.list({ cursor: page.next });
|
|
334
|
+
for (const prediction of page.results) {
|
|
335
|
+
console.log(prediction.id);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Models API
|
|
341
|
+
|
|
342
|
+
**Get Model Information:**
|
|
343
|
+
```javascript
|
|
344
|
+
const model = await replicate.models.get("stability-ai", "sdxl");
|
|
345
|
+
|
|
346
|
+
console.log(model.name);
|
|
347
|
+
console.log(model.description);
|
|
348
|
+
console.log(model.latest_version);
|
|
349
|
+
console.log(model.visibility); // "public" or "private"
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**List All Models:**
|
|
353
|
+
```javascript
|
|
354
|
+
// Automatic pagination
|
|
355
|
+
const allModels = [];
|
|
356
|
+
for await (const model of replicate.models.list()) {
|
|
357
|
+
allModels.push(model);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Manual pagination
|
|
361
|
+
let page = await replicate.models.list();
|
|
362
|
+
for (const model of page.results) {
|
|
363
|
+
console.log(model.owner, model.name);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
while (page.hasNextPage()) {
|
|
367
|
+
page = await page.getNextPage();
|
|
368
|
+
for (const model of page.results) {
|
|
369
|
+
console.log(model.owner, model.name);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Get Model Versions:**
|
|
375
|
+
```javascript
|
|
376
|
+
const versions = await replicate.models.versions.list(
|
|
377
|
+
"stability-ai",
|
|
378
|
+
"sdxl"
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
for await (const version of versions) {
|
|
382
|
+
console.log(version.id);
|
|
383
|
+
console.log(version.created_at);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
**Get Specific Version:**
|
|
388
|
+
```javascript
|
|
389
|
+
const version = await replicate.models.versions.get(
|
|
390
|
+
"stability-ai",
|
|
391
|
+
"sdxl",
|
|
392
|
+
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b"
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
console.log(version.openapi_schema); // Input/output schema
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Create a Model:**
|
|
399
|
+
```javascript
|
|
400
|
+
const model = await replicate.models.create({
|
|
401
|
+
owner: "your-username",
|
|
402
|
+
name: "my-custom-model",
|
|
403
|
+
description: "A custom model for specific tasks",
|
|
404
|
+
visibility: "private", // "public" or "private"
|
|
405
|
+
hardware: "gpu-a40-large"
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Collections API
|
|
410
|
+
|
|
411
|
+
**Get Collection:**
|
|
412
|
+
```javascript
|
|
413
|
+
const collection = await replicate.collections.get("text-to-image");
|
|
414
|
+
|
|
415
|
+
console.log(collection.name);
|
|
416
|
+
console.log(collection.description);
|
|
417
|
+
|
|
418
|
+
for (const model of collection.models) {
|
|
419
|
+
console.log(model.owner, model.name);
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
**List Featured Collections:**
|
|
424
|
+
```javascript
|
|
425
|
+
// Collections are curated lists of models available at replicate.com/collections
|
|
426
|
+
const collection = await replicate.collections.get("super-resolution");
|
|
427
|
+
|
|
428
|
+
collection.models.forEach(model => {
|
|
429
|
+
console.log(`${model.owner}/${model.name}: ${model.description}`);
|
|
430
|
+
});
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Deployments API
|
|
434
|
+
|
|
435
|
+
**Create a Deployment:**
|
|
436
|
+
```javascript
|
|
437
|
+
const deployment = await replicate.deployments.create({
|
|
438
|
+
name: "my-production-deployment",
|
|
439
|
+
model: "stability-ai/sdxl",
|
|
440
|
+
version: "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
441
|
+
hardware: "gpu-a40-large",
|
|
442
|
+
min_instances: 1,
|
|
443
|
+
max_instances: 5
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
console.log(deployment.url);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Available Hardware SKUs:** To list all available hardware SKUs and their specifications programmatically, use `await replicate.hardware.list()`. Common options include `"cpu"`, `"gpu-t4"`, `"gpu-a40-small"`, `"gpu-a40-large"`, and `"gpu-a100"`. From the CLI, run `replicate hardware list` to see all available hardware types with their SKUs, names, and specifications.
|
|
450
|
+
|
|
451
|
+
**Get Deployment:**
|
|
452
|
+
```javascript
|
|
453
|
+
const deployment = await replicate.deployments.get(
|
|
454
|
+
"your-username",
|
|
455
|
+
"my-production-deployment"
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
console.log(deployment.current_version);
|
|
459
|
+
console.log(deployment.hardware);
|
|
460
|
+
console.log(deployment.min_instances);
|
|
461
|
+
console.log(deployment.max_instances);
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Update Deployment:**
|
|
465
|
+
```javascript
|
|
466
|
+
const updated = await replicate.deployments.update(
|
|
467
|
+
"your-username",
|
|
468
|
+
"my-production-deployment",
|
|
469
|
+
{
|
|
470
|
+
version: "new-version-id",
|
|
471
|
+
min_instances: 2,
|
|
472
|
+
max_instances: 10
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**List Deployments:**
|
|
478
|
+
```javascript
|
|
479
|
+
for await (const deployment of replicate.deployments.list()) {
|
|
480
|
+
console.log(deployment.owner, deployment.name);
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
**Run Prediction on Deployment:**
|
|
485
|
+
```javascript
|
|
486
|
+
const prediction = await replicate.deployments.predictions.create(
|
|
487
|
+
"your-username",
|
|
488
|
+
"my-production-deployment",
|
|
489
|
+
{
|
|
490
|
+
input: {
|
|
491
|
+
prompt: "a beautiful sunset"
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
console.log(prediction.output);
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**Delete Deployment:**
|
|
500
|
+
```javascript
|
|
501
|
+
await replicate.deployments.delete(
|
|
502
|
+
"your-username",
|
|
503
|
+
"my-production-deployment"
|
|
504
|
+
);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Training API
|
|
508
|
+
|
|
509
|
+
**Create Training:**
|
|
510
|
+
```javascript
|
|
511
|
+
const training = await replicate.trainings.create(
|
|
512
|
+
"stability-ai",
|
|
513
|
+
"sdxl",
|
|
514
|
+
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
515
|
+
{
|
|
516
|
+
destination: "your-username/my-fine-tuned-model",
|
|
517
|
+
input: {
|
|
518
|
+
input_images: "https://example.com/training-data.zip",
|
|
519
|
+
learning_rate: 1e-6,
|
|
520
|
+
num_train_epochs: 100
|
|
521
|
+
},
|
|
522
|
+
webhook: "https://api.myapp.com/webhooks/training-complete"
|
|
523
|
+
}
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
console.log(training.id);
|
|
527
|
+
console.log(training.status); // "starting"
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**Get Training Status:**
|
|
531
|
+
```javascript
|
|
532
|
+
const training = await replicate.trainings.get("zz4ibbonubfz7carwiefibzgga");
|
|
533
|
+
|
|
534
|
+
console.log(training.status); // "succeeded", "processing", "failed", "canceled"
|
|
535
|
+
console.log(training.output); // New model version created
|
|
536
|
+
console.log(training.logs);
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**Cancel Training:**
|
|
540
|
+
```javascript
|
|
541
|
+
const canceled = await replicate.trainings.cancel("zz4ibbonubfz7carwiefibzgga");
|
|
542
|
+
console.log(canceled.status); // "canceled"
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
**List Trainings:**
|
|
546
|
+
```javascript
|
|
547
|
+
for await (const training of replicate.trainings.list()) {
|
|
548
|
+
console.log(training.id, training.status);
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Files API
|
|
553
|
+
|
|
554
|
+
**Upload File:**
|
|
555
|
+
```javascript
|
|
556
|
+
import fs from "fs";
|
|
557
|
+
|
|
558
|
+
const file = await replicate.files.create(
|
|
559
|
+
fs.readFileSync("path/to/image.png")
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
console.log(file.id);
|
|
563
|
+
console.log(file.urls.get); // URL to download the file
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**Use File in Prediction:**
|
|
567
|
+
```javascript
|
|
568
|
+
import fs from "fs";
|
|
569
|
+
|
|
570
|
+
// Upload file first
|
|
571
|
+
const file = await replicate.files.create(
|
|
572
|
+
fs.readFileSync("input-image.png")
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
// Use file handle in prediction
|
|
576
|
+
const prediction = await replicate.predictions.create({
|
|
577
|
+
version: "image-to-image-model-version-id",
|
|
578
|
+
input: {
|
|
579
|
+
image: file.urls.get,
|
|
580
|
+
prompt: "turn this into a watercolor painting"
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**File Encoding Strategy:**
|
|
586
|
+
```javascript
|
|
587
|
+
// Automatically upload files (default behavior)
|
|
588
|
+
const replicateAutoUpload = new Replicate({
|
|
589
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
590
|
+
fileEncodingStrategy: "upload"
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Manual file management (no automatic upload)
|
|
594
|
+
const replicateManual = new Replicate({
|
|
595
|
+
auth: process.env.REPLICATE_API_TOKEN,
|
|
596
|
+
fileEncodingStrategy: "no-upload"
|
|
597
|
+
});
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**Get File:**
|
|
601
|
+
```javascript
|
|
602
|
+
const file = await replicate.files.get("file-id-here");
|
|
603
|
+
console.log(file.urls.get);
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**List Files:**
|
|
607
|
+
```javascript
|
|
608
|
+
for await (const file of replicate.files.list()) {
|
|
609
|
+
console.log(file.id, file.created_at);
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
**Delete File:**
|
|
614
|
+
```javascript
|
|
615
|
+
await replicate.files.delete("file-id-here");
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Hardware API
|
|
619
|
+
|
|
620
|
+
**List Available Hardware:**
|
|
621
|
+
```javascript
|
|
622
|
+
const hardware = await replicate.hardware.list();
|
|
623
|
+
|
|
624
|
+
for (const sku of hardware) {
|
|
625
|
+
console.log(sku.name);
|
|
626
|
+
console.log(sku.sku);
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### Account API
|
|
631
|
+
|
|
632
|
+
**Get Account Information:**
|
|
633
|
+
```javascript
|
|
634
|
+
const account = await replicate.account.get();
|
|
635
|
+
|
|
636
|
+
console.log(account.type); // "user" or "organization"
|
|
637
|
+
console.log(account.username);
|
|
638
|
+
console.log(account.name);
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
## 5. Webhooks
|
|
642
|
+
|
|
643
|
+
### Setting Up Webhooks
|
|
644
|
+
|
|
645
|
+
**Create Prediction with Webhook:**
|
|
646
|
+
```javascript
|
|
647
|
+
const prediction = await replicate.predictions.create({
|
|
648
|
+
version: "model-version-id",
|
|
649
|
+
input: {
|
|
650
|
+
prompt: "a painting of a cat"
|
|
651
|
+
},
|
|
652
|
+
webhook: "https://api.myapp.com/webhooks/replicate",
|
|
653
|
+
webhook_events_filter: ["start", "output", "logs", "completed"]
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
**Webhook Event Types:** `"start"` fires when prediction starts processing. `"output"` fires each time prediction generates output (throttled to max 1 per 500ms). `"logs"` fires each time log output is generated (throttled to max 1 per 500ms). `"completed"` fires when prediction reaches terminal state (succeeded/failed/canceled).
|
|
658
|
+
|
|
659
|
+
**Webhook Payload Example:**
|
|
660
|
+
```javascript
|
|
661
|
+
{
|
|
662
|
+
"id": "gm3qorzdhgbfurvjtvhg6dckhu",
|
|
663
|
+
"status": "succeeded",
|
|
664
|
+
"output": ["https://replicate.delivery/output.png"],
|
|
665
|
+
"created_at": "2024-01-15T10:30:00.000Z",
|
|
666
|
+
"started_at": "2024-01-15T10:30:01.000Z",
|
|
667
|
+
"completed_at": "2024-01-15T10:30:05.000Z",
|
|
668
|
+
"metrics": {
|
|
669
|
+
"predict_time": 4.2
|
|
670
|
+
},
|
|
671
|
+
"logs": "Processing complete",
|
|
672
|
+
"error": null
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**Webhook Handler (Express.js):**
|
|
677
|
+
```javascript
|
|
678
|
+
import express from "express";
|
|
679
|
+
import crypto from "crypto";
|
|
680
|
+
|
|
681
|
+
const app = express();
|
|
682
|
+
app.use(express.json());
|
|
683
|
+
|
|
684
|
+
app.post("/webhooks/replicate", async (req, res) => {
|
|
685
|
+
const prediction = req.body;
|
|
686
|
+
|
|
687
|
+
console.log("Webhook received:", prediction.id);
|
|
688
|
+
console.log("Status:", prediction.status);
|
|
689
|
+
|
|
690
|
+
if (prediction.status === "succeeded") {
|
|
691
|
+
console.log("Output:", prediction.output);
|
|
692
|
+
// Process the output
|
|
693
|
+
await processOutput(prediction.output);
|
|
694
|
+
} else if (prediction.status === "failed") {
|
|
695
|
+
console.error("Prediction failed:", prediction.error);
|
|
696
|
+
// Handle failure
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Always respond quickly to webhooks
|
|
700
|
+
res.status(200).json({ received: true });
|
|
701
|
+
});
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Webhook Best Practices:** Respond to webhooks within 30 seconds with 200 OK. Process webhook payloads asynchronously (don't block the response). Implement idempotency since webhooks may be retried. Replicate will retry failed webhooks automatically. Use HTTPS endpoints for webhooks. Validate webhook authenticity in production.
|
|
705
|
+
|
|
706
|
+
### Webhook Security
|
|
707
|
+
|
|
708
|
+
**Implement Webhook Signature Verification (recommended for production):**
|
|
709
|
+
```javascript
|
|
710
|
+
// Note: Replicate webhook signature verification details
|
|
711
|
+
// Check Replicate's documentation for current signature scheme
|
|
712
|
+
|
|
713
|
+
app.post("/webhooks/replicate", (req, res) => {
|
|
714
|
+
const signature = req.headers['x-replicate-signature'];
|
|
715
|
+
const secret = process.env.WEBHOOK_SECRET;
|
|
716
|
+
|
|
717
|
+
// Verify signature (implementation depends on Replicate's scheme)
|
|
718
|
+
if (!verifySignature(signature, req.body, secret)) {
|
|
719
|
+
return res.status(401).json({ error: "Invalid signature" });
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Process webhook
|
|
723
|
+
const prediction = req.body;
|
|
724
|
+
processWebhook(prediction);
|
|
725
|
+
|
|
726
|
+
res.status(200).json({ received: true });
|
|
727
|
+
});
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
## 6. Advanced Features
|
|
731
|
+
|
|
732
|
+
### Error Handling
|
|
733
|
+
|
|
734
|
+
**Comprehensive Error Handling:**
|
|
735
|
+
```javascript
|
|
736
|
+
import Replicate from "replicate";
|
|
737
|
+
|
|
738
|
+
async function runModelSafely() {
|
|
739
|
+
try {
|
|
740
|
+
const output = await replicate.run(
|
|
741
|
+
"stability-ai/sdxl",
|
|
742
|
+
{
|
|
743
|
+
input: {
|
|
744
|
+
prompt: "a beautiful landscape"
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
return output;
|
|
750
|
+
} catch (error) {
|
|
751
|
+
// Handle specific error types
|
|
752
|
+
if (error.response) {
|
|
753
|
+
// API error response
|
|
754
|
+
console.error("Status:", error.response.status);
|
|
755
|
+
console.error("Error:", error.response.data);
|
|
756
|
+
|
|
757
|
+
if (error.response.status === 401) {
|
|
758
|
+
throw new Error("Invalid API token");
|
|
759
|
+
} else if (error.response.status === 402) {
|
|
760
|
+
throw new Error("Insufficient credits");
|
|
761
|
+
} else if (error.response.status === 429) {
|
|
762
|
+
throw new Error("Rate limit exceeded");
|
|
763
|
+
} else if (error.response.status === 500) {
|
|
764
|
+
throw new Error("Replicate server error");
|
|
765
|
+
}
|
|
766
|
+
} else if (error.request) {
|
|
767
|
+
// Network error
|
|
768
|
+
console.error("Network error:", error.message);
|
|
769
|
+
throw new Error("Failed to connect to Replicate API");
|
|
770
|
+
} else {
|
|
771
|
+
// Other errors
|
|
772
|
+
console.error("Error:", error.message);
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
**Retry Logic with Exponential Backoff:**
|
|
780
|
+
```javascript
|
|
781
|
+
async function runWithRetry(identifier, options, maxRetries = 3) {
|
|
782
|
+
let lastError;
|
|
783
|
+
|
|
784
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
785
|
+
try {
|
|
786
|
+
const output = await replicate.run(identifier, options);
|
|
787
|
+
return output;
|
|
788
|
+
} catch (error) {
|
|
789
|
+
lastError = error;
|
|
790
|
+
|
|
791
|
+
// Only retry on transient errors
|
|
792
|
+
const isRetryable =
|
|
793
|
+
error.response?.status === 429 || // Rate limit
|
|
794
|
+
error.response?.status === 500 || // Server error
|
|
795
|
+
error.response?.status === 503 || // Service unavailable
|
|
796
|
+
!error.response; // Network error
|
|
797
|
+
|
|
798
|
+
if (!isRetryable || attempt === maxRetries - 1) {
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Exponential backoff: 1s, 2s, 4s, etc.
|
|
803
|
+
const delay = Math.pow(2, attempt) * 1000;
|
|
804
|
+
console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
|
|
805
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
throw lastError;
|
|
810
|
+
}
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Polling vs Blocking
|
|
814
|
+
|
|
815
|
+
**Blocking Mode (holds connection open):**
|
|
816
|
+
```javascript
|
|
817
|
+
const output = await replicate.run(
|
|
818
|
+
"meta/llama-2-70b-chat",
|
|
819
|
+
{
|
|
820
|
+
input: { prompt: "Hello" },
|
|
821
|
+
wait: {
|
|
822
|
+
mode: "block", // Hold connection open
|
|
823
|
+
interval: 60000 // Fallback to polling after 60s
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
);
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**Polling Mode (repeated requests):**
|
|
830
|
+
```javascript
|
|
831
|
+
const output = await replicate.run(
|
|
832
|
+
"meta/llama-2-70b-chat",
|
|
833
|
+
{
|
|
834
|
+
input: { prompt: "Hello" },
|
|
835
|
+
wait: {
|
|
836
|
+
mode: "poll", // Make repeated requests
|
|
837
|
+
interval: 500 // Check every 500ms
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
);
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
### Async/Await Patterns
|
|
844
|
+
|
|
845
|
+
**Parallel Predictions:**
|
|
846
|
+
```javascript
|
|
847
|
+
const prompts = [
|
|
848
|
+
"a sunset over mountains",
|
|
849
|
+
"a city at night",
|
|
850
|
+
"a forest in autumn"
|
|
851
|
+
];
|
|
852
|
+
|
|
853
|
+
const predictions = await Promise.all(
|
|
854
|
+
prompts.map(prompt =>
|
|
855
|
+
replicate.predictions.create({
|
|
856
|
+
version: "model-version-id",
|
|
857
|
+
input: { prompt }
|
|
858
|
+
})
|
|
859
|
+
)
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
// Wait for all to complete
|
|
863
|
+
const results = await Promise.all(
|
|
864
|
+
predictions.map(p => replicate.wait(p))
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
results.forEach((result, i) => {
|
|
868
|
+
console.log(`Result ${i}:`, result.output);
|
|
869
|
+
});
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
**Sequential Processing with Rate Limiting:**
|
|
873
|
+
```javascript
|
|
874
|
+
async function processSequentially(prompts, delayMs = 1000) {
|
|
875
|
+
const results = [];
|
|
876
|
+
|
|
877
|
+
for (const prompt of prompts) {
|
|
878
|
+
const output = await replicate.run(
|
|
879
|
+
"stability-ai/sdxl",
|
|
880
|
+
{ input: { prompt } }
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
results.push(output);
|
|
884
|
+
|
|
885
|
+
// Delay between requests
|
|
886
|
+
if (prompts.indexOf(prompt) < prompts.length - 1) {
|
|
887
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
return results;
|
|
892
|
+
}
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
## 7. Best Practices
|
|
896
|
+
|
|
897
|
+
### Request Structure
|
|
898
|
+
|
|
899
|
+
**Always specify exact versions in production:**
|
|
900
|
+
```javascript
|
|
901
|
+
// Good - pinned version
|
|
902
|
+
const output = await replicate.run(
|
|
903
|
+
"stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
|
904
|
+
{ input: { prompt: "a cat" } }
|
|
905
|
+
);
|
|
906
|
+
|
|
907
|
+
// Avoid - uses latest version (can change unexpectedly)
|
|
908
|
+
const output = await replicate.run(
|
|
909
|
+
"stability-ai/sdxl",
|
|
910
|
+
{ input: { prompt: "a cat" } }
|
|
911
|
+
);
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
**Validate inputs before sending:**
|
|
915
|
+
```javascript
|
|
916
|
+
function validateInput(input) {
|
|
917
|
+
if (!input.prompt || input.prompt.trim().length === 0) {
|
|
918
|
+
throw new Error("Prompt is required");
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if (input.width && (input.width < 256 || input.width > 2048)) {
|
|
922
|
+
throw new Error("Width must be between 256 and 2048");
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if (input.height && (input.height < 256 || input.height > 2048)) {
|
|
926
|
+
throw new Error("Height must be between 256 and 2048");
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
return true;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// Use validation
|
|
933
|
+
const input = { prompt: "a landscape", width: 1024, height: 1024 };
|
|
934
|
+
validateInput(input);
|
|
935
|
+
|
|
936
|
+
const output = await replicate.run("stability-ai/sdxl", { input });
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
### Rate Limits and Retries
|
|
940
|
+
|
|
941
|
+
**Implement exponential backoff:**
|
|
942
|
+
```javascript
|
|
943
|
+
async function callWithBackoff(fn, maxRetries = 3) {
|
|
944
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
945
|
+
try {
|
|
946
|
+
return await fn();
|
|
947
|
+
} catch (error) {
|
|
948
|
+
if (error.response?.status === 429) {
|
|
949
|
+
const retryAfter = error.response.headers['retry-after'];
|
|
950
|
+
const delay = retryAfter
|
|
951
|
+
? parseInt(retryAfter) * 1000
|
|
952
|
+
: Math.pow(2, i) * 1000;
|
|
953
|
+
|
|
954
|
+
console.log(`Rate limited. Retrying after ${delay}ms`);
|
|
955
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
956
|
+
} else {
|
|
957
|
+
throw error;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
throw new Error("Max retries exceeded");
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Usage
|
|
966
|
+
const output = await callWithBackoff(() =>
|
|
967
|
+
replicate.run("model-name", { input: { prompt: "test" } })
|
|
968
|
+
);
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
**Respect Retry-After headers:**
|
|
972
|
+
```javascript
|
|
973
|
+
catch (error) {
|
|
974
|
+
if (error.response?.status === 429) {
|
|
975
|
+
const retryAfter = error.response.headers['retry-after'];
|
|
976
|
+
if (retryAfter) {
|
|
977
|
+
const delaySeconds = parseInt(retryAfter);
|
|
978
|
+
console.log(`Waiting ${delaySeconds}s before retry`);
|
|
979
|
+
await new Promise(resolve => setTimeout(resolve, delaySeconds * 1000));
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
### Safety and Compliance
|
|
986
|
+
|
|
987
|
+
**Content moderation:**
|
|
988
|
+
```javascript
|
|
989
|
+
function checkContentSafety(prompt) {
|
|
990
|
+
// Implement your content policy
|
|
991
|
+
const blockedTerms = ['harmful', 'illegal'];
|
|
992
|
+
|
|
993
|
+
const normalized = prompt.toLowerCase();
|
|
994
|
+
for (const term of blockedTerms) {
|
|
995
|
+
if (normalized.includes(term)) {
|
|
996
|
+
throw new Error("Content policy violation");
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
return true;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// Use before API calls
|
|
1004
|
+
try {
|
|
1005
|
+
checkContentSafety(userPrompt);
|
|
1006
|
+
const output = await replicate.run("model", { input: { prompt: userPrompt } });
|
|
1007
|
+
} catch (error) {
|
|
1008
|
+
console.error("Safety check failed:", error.message);
|
|
1009
|
+
}
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
**Monitor and log predictions:**
|
|
1013
|
+
```javascript
|
|
1014
|
+
async function runWithLogging(identifier, options) {
|
|
1015
|
+
const startTime = Date.now();
|
|
1016
|
+
|
|
1017
|
+
try {
|
|
1018
|
+
const prediction = await replicate.predictions.create({
|
|
1019
|
+
version: identifier,
|
|
1020
|
+
input: options.input
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
console.log({
|
|
1024
|
+
event: "prediction_created",
|
|
1025
|
+
id: prediction.id,
|
|
1026
|
+
model: identifier,
|
|
1027
|
+
timestamp: new Date().toISOString()
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
const result = await replicate.wait(prediction);
|
|
1031
|
+
const duration = Date.now() - startTime;
|
|
1032
|
+
|
|
1033
|
+
console.log({
|
|
1034
|
+
event: "prediction_completed",
|
|
1035
|
+
id: result.id,
|
|
1036
|
+
status: result.status,
|
|
1037
|
+
duration_ms: duration,
|
|
1038
|
+
cost_estimate: result.metrics?.predict_time,
|
|
1039
|
+
timestamp: new Date().toISOString()
|
|
1040
|
+
});
|
|
1041
|
+
|
|
1042
|
+
return result.output;
|
|
1043
|
+
} catch (error) {
|
|
1044
|
+
console.error({
|
|
1045
|
+
event: "prediction_failed",
|
|
1046
|
+
error: error.message,
|
|
1047
|
+
duration_ms: Date.now() - startTime,
|
|
1048
|
+
timestamp: new Date().toISOString()
|
|
1049
|
+
});
|
|
1050
|
+
throw error;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
### Cost Management
|
|
1056
|
+
|
|
1057
|
+
**Estimate costs before running:**
|
|
1058
|
+
```javascript
|
|
1059
|
+
// Pricing varies by hardware
|
|
1060
|
+
const PRICING = {
|
|
1061
|
+
"cpu": 0.0001, // $0.0001/sec
|
|
1062
|
+
"gpu-t4": 0.000225, // $0.000225/sec for public models
|
|
1063
|
+
"gpu-a40-small": 0.000575,
|
|
1064
|
+
"gpu-a40-large": 0.00118,
|
|
1065
|
+
"gpu-a100": 0.00385
|
|
1066
|
+
};
|
|
1067
|
+
|
|
1068
|
+
function estimateCost(hardwareSku, estimatedSeconds) {
|
|
1069
|
+
const pricePerSecond = PRICING[hardwareSku] || 0;
|
|
1070
|
+
return pricePerSecond * estimatedSeconds;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
// Use deployments for predictable costs
|
|
1074
|
+
const deployment = await replicate.deployments.create({
|
|
1075
|
+
name: "cost-controlled-deployment",
|
|
1076
|
+
model: "stability-ai/sdxl",
|
|
1077
|
+
version: "version-id",
|
|
1078
|
+
hardware: "gpu-t4", // Choose appropriate hardware
|
|
1079
|
+
min_instances: 0, // Scale to zero when not in use
|
|
1080
|
+
max_instances: 2 // Cap maximum concurrent instances
|
|
1081
|
+
});
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
**Cancel long-running predictions:**
|
|
1085
|
+
```javascript
|
|
1086
|
+
const prediction = await replicate.predictions.create({
|
|
1087
|
+
version: "model-version",
|
|
1088
|
+
input: { prompt: "test" }
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
// Set timeout to prevent excessive costs
|
|
1092
|
+
const timeout = setTimeout(async () => {
|
|
1093
|
+
console.log("Prediction taking too long, canceling...");
|
|
1094
|
+
await replicate.predictions.cancel(prediction.id);
|
|
1095
|
+
}, 60000); // Cancel after 60 seconds
|
|
1096
|
+
|
|
1097
|
+
try {
|
|
1098
|
+
const result = await replicate.wait(prediction);
|
|
1099
|
+
clearTimeout(timeout);
|
|
1100
|
+
return result.output;
|
|
1101
|
+
} catch (error) {
|
|
1102
|
+
clearTimeout(timeout);
|
|
1103
|
+
throw error;
|
|
1104
|
+
}
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
## 8. Production Patterns
|
|
1108
|
+
|
|
1109
|
+
### Checking SDK and Model Versions
|
|
1110
|
+
|
|
1111
|
+
To check the latest SDK version:
|
|
1112
|
+
```bash
|
|
1113
|
+
npm view replicate version
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
To list model versions programmatically:
|
|
1117
|
+
```javascript
|
|
1118
|
+
const versions = await replicate.models.versions.list("owner", "model-name");
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
To check model schema and version details from CLI:
|
|
1122
|
+
```bash
|
|
1123
|
+
replicate model schema owner/model-name
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
### Error Tracking Integration
|
|
1127
|
+
|
|
1128
|
+
```javascript
|
|
1129
|
+
import * as Sentry from "@sentry/node";
|
|
1130
|
+
|
|
1131
|
+
try {
|
|
1132
|
+
const output = await replicate.run(identifier, options);
|
|
1133
|
+
} catch (error) {
|
|
1134
|
+
Sentry.captureException(error, {
|
|
1135
|
+
tags: {
|
|
1136
|
+
service: "replicate",
|
|
1137
|
+
model: identifier
|
|
1138
|
+
},
|
|
1139
|
+
contexts: {
|
|
1140
|
+
prediction: {
|
|
1141
|
+
input: options.input
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
throw error;
|
|
1146
|
+
}
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
### Account Information
|
|
1150
|
+
|
|
1151
|
+
```javascript
|
|
1152
|
+
const account = await replicate.account.get();
|
|
1153
|
+
console.log(account.type); // "user" or "organization"
|
|
1154
|
+
console.log(account.username);
|
|
1155
|
+
console.log(account.name);
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
### Testing with Mocks
|
|
1159
|
+
|
|
1160
|
+
```javascript
|
|
1161
|
+
import { jest } from '@jest/globals';
|
|
1162
|
+
|
|
1163
|
+
jest.mock('replicate');
|
|
1164
|
+
|
|
1165
|
+
test('handles prediction success', async () => {
|
|
1166
|
+
const mockRun = jest.fn().mockResolvedValue(['output.png']);
|
|
1167
|
+
const replicate = { run: mockRun };
|
|
1168
|
+
|
|
1169
|
+
const result = await myFunction(replicate);
|
|
1170
|
+
|
|
1171
|
+
expect(mockRun).toHaveBeenCalledWith(
|
|
1172
|
+
expect.any(String),
|
|
1173
|
+
expect.objectContaining({
|
|
1174
|
+
input: expect.any(Object)
|
|
1175
|
+
})
|
|
1176
|
+
);
|
|
1177
|
+
expect(result).toBeDefined();
|
|
1178
|
+
});
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
### Input Validation
|
|
1182
|
+
|
|
1183
|
+
To inspect a model's expected input/output schema:
|
|
1184
|
+
```javascript
|
|
1185
|
+
const version = await replicate.models.versions.get("owner", "model", "version-id");
|
|
1186
|
+
console.log(version.openapi_schema);
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
From CLI:
|
|
1190
|
+
```bash
|
|
1191
|
+
replicate model schema owner/model-name
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1194
|
+
Validation example:
|
|
1195
|
+
```javascript
|
|
1196
|
+
import validator from 'validator';
|
|
1197
|
+
|
|
1198
|
+
function validatePredictionInput(input) {
|
|
1199
|
+
if (!input.prompt || typeof input.prompt !== 'string') {
|
|
1200
|
+
throw new Error('Invalid prompt');
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (input.prompt.length > 10000) {
|
|
1204
|
+
throw new Error('Prompt too long');
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
if (input.image_url && !validator.isURL(input.image_url)) {
|
|
1208
|
+
throw new Error('Invalid image URL');
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
return true;
|
|
1212
|
+
}
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
### Monitoring with Metrics
|
|
1216
|
+
|
|
1217
|
+
List and monitor predictions:
|
|
1218
|
+
```javascript
|
|
1219
|
+
for await (const prediction of replicate.predictions.list()) {
|
|
1220
|
+
console.log(prediction.id, prediction.status);
|
|
1221
|
+
}
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
Monitor trainings:
|
|
1225
|
+
```javascript
|
|
1226
|
+
for await (const training of replicate.trainings.list()) {
|
|
1227
|
+
console.log(training.id, training.status);
|
|
1228
|
+
}
|
|
1229
|
+
```
|
|
1230
|
+
|
|
1231
|
+
Prometheus integration:
|
|
1232
|
+
```javascript
|
|
1233
|
+
import prometheus from 'prom-client';
|
|
1234
|
+
|
|
1235
|
+
const predictionCounter = new prometheus.Counter({
|
|
1236
|
+
name: 'replicate_predictions_total',
|
|
1237
|
+
help: 'Total number of predictions',
|
|
1238
|
+
labelNames: ['model', 'status']
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1241
|
+
const predictionDuration = new prometheus.Histogram({
|
|
1242
|
+
name: 'replicate_prediction_duration_seconds',
|
|
1243
|
+
help: 'Prediction duration in seconds',
|
|
1244
|
+
labelNames: ['model']
|
|
1245
|
+
});
|
|
1246
|
+
|
|
1247
|
+
async function runWithMetrics(identifier, options) {
|
|
1248
|
+
const startTime = Date.now();
|
|
1249
|
+
|
|
1250
|
+
try {
|
|
1251
|
+
const output = await replicate.run(identifier, options);
|
|
1252
|
+
predictionCounter.inc({ model: identifier, status: 'success' });
|
|
1253
|
+
return output;
|
|
1254
|
+
} catch (error) {
|
|
1255
|
+
predictionCounter.inc({ model: identifier, status: 'error' });
|
|
1256
|
+
throw error;
|
|
1257
|
+
} finally {
|
|
1258
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
1259
|
+
predictionDuration.observe({ model: identifier }, duration);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
### Deployment Management
|
|
1265
|
+
|
|
1266
|
+
Create deployment:
|
|
1267
|
+
```javascript
|
|
1268
|
+
const deployment = await replicate.deployments.create({
|
|
1269
|
+
name: "production-deployment",
|
|
1270
|
+
model: "stability-ai/sdxl",
|
|
1271
|
+
version: "pinned-version-id",
|
|
1272
|
+
hardware: "gpu-a40-large",
|
|
1273
|
+
min_instances: 2,
|
|
1274
|
+
max_instances: 10
|
|
1275
|
+
});
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
Update deployment:
|
|
1279
|
+
```javascript
|
|
1280
|
+
const updated = await replicate.deployments.update(
|
|
1281
|
+
"your-username",
|
|
1282
|
+
"deployment-name",
|
|
1283
|
+
{
|
|
1284
|
+
version: "new-version-id",
|
|
1285
|
+
min_instances: 0,
|
|
1286
|
+
max_instances: 5
|
|
1287
|
+
}
|
|
1288
|
+
);
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1291
|
+
Delete deployment:
|
|
1292
|
+
```javascript
|
|
1293
|
+
await replicate.deployments.delete("your-username", "deployment-name");
|
|
1294
|
+
```
|
|
1295
|
+
|
|
1296
|
+
List deployments:
|
|
1297
|
+
```javascript
|
|
1298
|
+
for await (const deployment of replicate.deployments.list()) {
|
|
1299
|
+
console.log(deployment.owner, deployment.name);
|
|
1300
|
+
}
|
|
1301
|
+
```
|
|
1302
|
+
|
|
1303
|
+
From CLI:
|
|
1304
|
+
```bash
|
|
1305
|
+
replicate model create yourname/model --private --hardware gpu-a40-small
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
### Canceling Predictions
|
|
1309
|
+
|
|
1310
|
+
Cancel programmatically:
|
|
1311
|
+
```javascript
|
|
1312
|
+
await replicate.predictions.cancel(prediction_id);
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
From CLI:
|
|
1316
|
+
```bash
|
|
1317
|
+
replicate prediction cancel <id>
|
|
1318
|
+
```
|