diff --git a/.changeset/unlucky-wombats-heal.md b/.changeset/unlucky-wombats-heal.md new file mode 100644 index 000000000..071da4fff --- /dev/null +++ b/.changeset/unlucky-wombats-heal.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/openai": patch +--- + +Upgrade to openai-node SDK 4.13.0, add support for request options and defaultQuery/defaultHeaders diff --git a/integrations/openai/package.json b/integrations/openai/package.json index c9eeeee14..47ca27182 100644 --- a/integrations/openai/package.json +++ b/integrations/openai/package.json @@ -16,19 +16,21 @@ "@trigger.dev/tsconfig": "workspace:*", "@types/node": "18", "rimraf": "^3.0.2", - "tsup": "^6.5.0" + "tsup": "^6.5.0", + "typescript": "^4.9.4" }, "scripts": { "clean": "rimraf dist", "build": "npm run clean && npm run build:tsup", - "build:tsup": "tsup" + "build:tsup": "tsup", + "typecheck": "tsc --noEmit" }, "dependencies": { - "openai": "^4.2.0", + "openai": "^4.13.0", "@trigger.dev/sdk": "workspace:^2.2.1", "@trigger.dev/integration-kit": "workspace:^2.2.1" }, "engines": { - "node": ">=16.8.0" + "node": ">=18.0.0" } } \ No newline at end of file diff --git a/integrations/openai/src/chat.ts b/integrations/openai/src/chat.ts index 6ded6ec8a..8c05ab8e7 100644 --- a/integrations/openai/src/chat.ts +++ b/integrations/openai/src/chat.ts @@ -1,21 +1,32 @@ -import { IntegrationTaskKey, Prettify, redactString } from "@trigger.dev/sdk"; +import { IntegrationTaskKey, Prettify } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; -import { createTaskUsageProperties } from "./taskUtils"; +import { + backgroundTaskRetries, + createBackgroundFetchHeaders, + createBackgroundFetchUrl, + createTaskUsageProperties, +} from "./taskUtils"; +import { OpenAIIntegrationOptions, OpenAIRequestOptions } from "./types"; export class Chat { - constructor(private runTask: OpenAIRunTask) {} + constructor( + private runTask: OpenAIRunTask, + private options: OpenAIIntegrationOptions + ) {} completions = { create: ( key: IntegrationTaskKey, - params: Prettify + params: Prettify, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task) => { const response = await client.chat.completions.create(params, { idempotencyKey: task.idempotencyKey, + ...options, }); task.outputProperties = createTaskUsageProperties(response.usage); return response; @@ -35,49 +46,33 @@ export class Chat { backgroundCreate: ( key: IntegrationTaskKey, - params: Prettify + params: Prettify, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task, io) => { - let baseURL = client.baseURL ?? "https://api.openai.com/v1"; - if (baseURL.endsWith("/")) { - baseURL = baseURL.slice(0, -1); - } - - const chatCompletionsURL = `${baseURL}/chat/completions`; + const url = createBackgroundFetchUrl( + client, + "/chat/completions", + this.options.defaultQuery, + options + ); const response = await io.backgroundFetch( "background", - chatCompletionsURL, + url, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: redactString`Bearer ${client.apiKey}`, - ...(client.organization ? { "OpenAI-Organization": client.organization } : {}), - "Idempotency-Key": task.idempotencyKey, - }, + method: options.method ?? "POST", + headers: createBackgroundFetchHeaders( + client, + task.idempotencyKey, + this.options.defaultHeaders, + options + ), body: JSON.stringify(params), }, - { - "500-599": { - strategy: "backoff", - limit: 5, - minTimeoutInMs: 1000, - maxTimeoutInMs: 30000, - factor: 1.8, - randomize: true, - }, - "429": { - strategy: "backoff", - limit: 10, - minTimeoutInMs: 1000, - maxTimeoutInMs: 60000, - factor: 2, - randomize: true, - }, - } + backgroundTaskRetries ); task.outputProperties = createTaskUsageProperties(response.usage); diff --git a/integrations/openai/src/completions.ts b/integrations/openai/src/completions.ts index 8f27ea971..0d4198b57 100644 --- a/integrations/openai/src/completions.ts +++ b/integrations/openai/src/completions.ts @@ -1,24 +1,31 @@ import { IntegrationTaskKey, Prettify, redactString } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; -import { createTaskUsageProperties } from "./taskUtils"; +import { + backgroundTaskRetries, + createBackgroundFetchHeaders, + createBackgroundFetchUrl, + createTaskUsageProperties, +} from "./taskUtils"; +import { OpenAIIntegrationOptions, OpenAIRequestOptions } from "./types"; export class Completions { - runTask: OpenAIRunTask; - - constructor(runTask: OpenAIRunTask) { - this.runTask = runTask; - } + constructor( + private runTask: OpenAIRunTask, + private options: OpenAIIntegrationOptions + ) {} create( key: IntegrationTaskKey, - params: Prettify + params: Prettify, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task) => { const response = await client.completions.create(params, { idempotencyKey: task.idempotencyKey, + ...options, }); task.outputProperties = createTaskUsageProperties(response.usage); return response; @@ -38,49 +45,33 @@ export class Completions { backgroundCreate( key: IntegrationTaskKey, - params: Prettify + params: Prettify, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task, io) => { - let baseURL = client.baseURL ?? "https://api.openai.com/v1"; - if (baseURL.endsWith("/")) { - baseURL = baseURL.slice(0, -1); - } - - const chatCompletionsURL = `${baseURL}/chat/completions`; + const url = createBackgroundFetchUrl( + client, + "/completions", + this.options.defaultQuery, + options + ); const response = await io.backgroundFetch( "background", - chatCompletionsURL, + url, { method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: redactString`Bearer ${client.apiKey}`, - ...(client.organization ? { "OpenAI-Organization": client.organization } : {}), - "Idempotency-Key": task.idempotencyKey, - }, + headers: createBackgroundFetchHeaders( + client, + task.idempotencyKey, + this.options.defaultHeaders, + options + ), body: JSON.stringify(params), }, - { - "500-599": { - strategy: "backoff", - limit: 5, - minTimeoutInMs: 1000, - maxTimeoutInMs: 30000, - factor: 1.8, - randomize: true, - }, - "429": { - strategy: "backoff", - limit: 10, - minTimeoutInMs: 1000, - maxTimeoutInMs: 60000, - factor: 2, - randomize: true, - }, - } + backgroundTaskRetries ); task.outputProperties = createTaskUsageProperties(response.usage); diff --git a/integrations/openai/src/edits.ts b/integrations/openai/src/edits.ts index dd2ee7928..4ba2856e5 100644 --- a/integrations/openai/src/edits.ts +++ b/integrations/openai/src/edits.ts @@ -3,6 +3,7 @@ import { IntegrationTaskKey, Prettify } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; import { createTaskUsageProperties } from "./taskUtils"; +import { OpenAIRequestOptions } from "./types"; export class Edits { runTask: OpenAIRunTask; @@ -14,7 +15,11 @@ export class Edits { /** * @deprecated The Edits API is deprecated; please use Chat Completions instead. */ - create(key: IntegrationTaskKey, params: Prettify): Promise { + create( + key: IntegrationTaskKey, + params: Prettify, + options: OpenAIRequestOptions = {} + ): Promise { let properties = [ { label: "Model", @@ -37,7 +42,10 @@ export class Edits { return this.runTask( key, async (client, task) => { - const response = await client.edits.create(params, { idempotencyKey: task.idempotencyKey }); + const response = await client.edits.create(params, { + idempotencyKey: task.idempotencyKey, + ...options, + }); task.outputProperties = createTaskUsageProperties(response.usage); return response; }, diff --git a/integrations/openai/src/embeddings.ts b/integrations/openai/src/embeddings.ts index 0594095ac..ef322476a 100644 --- a/integrations/openai/src/embeddings.ts +++ b/integrations/openai/src/embeddings.ts @@ -2,6 +2,7 @@ import { IntegrationTaskKey } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; import { createTaskUsageProperties } from "./taskUtils"; +import { OpenAIRequestOptions } from "./types"; export class Embeddings { runTask: OpenAIRunTask; @@ -12,13 +13,15 @@ export class Embeddings { create( key: IntegrationTaskKey, - params: OpenAI.EmbeddingCreateParams + params: OpenAI.EmbeddingCreateParams, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task) => { const response = await client.embeddings.create(params, { idempotencyKey: task.idempotencyKey, + ...options, }); task.outputProperties = createTaskUsageProperties(response.usage); return response; diff --git a/integrations/openai/src/files.ts b/integrations/openai/src/files.ts index e15556a3f..a67276e51 100644 --- a/integrations/openai/src/files.ts +++ b/integrations/openai/src/files.ts @@ -2,6 +2,7 @@ import { fileFromString } from "@trigger.dev/integration-kit"; import { IntegrationTaskKey } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; +import { OpenAIRequestOptions } from "./types"; type CreateFileRequest = { file: string | File; @@ -24,7 +25,11 @@ export class Files { this.runTask = runTask; } - create(key: IntegrationTaskKey, params: CreateFileRequest): Promise { + create( + key: IntegrationTaskKey, + params: CreateFileRequest, + options: OpenAIRequestOptions = {} + ): Promise { return this.runTask( key, async (client, task) => { @@ -38,7 +43,7 @@ export class Files { return client.files.create( { file, purpose: params.purpose }, - { idempotencyKey: task.idempotencyKey } + { idempotencyKey: task.idempotencyKey, ...options } ); }, { @@ -58,11 +63,14 @@ export class Files { ); } - list(key: IntegrationTaskKey): Promise { + list( + key: IntegrationTaskKey, + options: OpenAIRequestOptions = {} + ): Promise { return this.runTask( key, async (client, task) => { - const response = await client.files.list(); + const response = await client.files.list(options); return response.data; }, { @@ -74,7 +82,8 @@ export class Files { createFineTune( key: IntegrationTaskKey, - params: CreateFineTuneFileRequest + params: CreateFineTuneFileRequest, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, @@ -86,7 +95,7 @@ export class Files { return client.files.create( { file, purpose: "fine-tune" }, - { idempotencyKey: task.idempotencyKey } + { idempotencyKey: task.idempotencyKey, ...options } ); }, { diff --git a/integrations/openai/src/fineTunes.ts b/integrations/openai/src/fineTunes.ts index 6b8917ca1..c103517ae 100644 --- a/integrations/openai/src/fineTunes.ts +++ b/integrations/openai/src/fineTunes.ts @@ -1,6 +1,7 @@ import { IntegrationTaskKey } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; +import { OpenAIRequestOptions } from "./types"; type SpecificFineTuneRequest = { fineTuneId: string; @@ -15,7 +16,8 @@ export class FineTunes { create( key: IntegrationTaskKey, - params: OpenAI.FineTuneCreateParams + params: OpenAI.FineTuneCreateParams, + options: OpenAIRequestOptions = {} ): Promise { let properties = [ { @@ -41,7 +43,7 @@ export class FineTunes { return this.runTask( key, async (client, task) => { - return client.fineTunes.create(params, { idempotencyKey: task.idempotencyKey }); + return client.fineTunes.create(params, { idempotencyKey: task.idempotencyKey, ...options }); }, { name: "Create fine tune", @@ -51,11 +53,14 @@ export class FineTunes { ); } - list(key: IntegrationTaskKey): Promise { + list( + key: IntegrationTaskKey, + options: OpenAIRequestOptions = {} + ): Promise { return this.runTask( key, async (client, task) => { - const response = await client.fineTunes.list(); + const response = await client.fineTunes.list(options); return response.data; }, { @@ -67,12 +72,13 @@ export class FineTunes { retrieve( key: IntegrationTaskKey, - params: SpecificFineTuneRequest + params: SpecificFineTuneRequest, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task) => { - return client.fineTunes.retrieve(params.fineTuneId); + return client.fineTunes.retrieve(params.fineTuneId, options); }, { name: "Retrieve fine tune", @@ -89,12 +95,16 @@ export class FineTunes { cancel( key: IntegrationTaskKey, - params: SpecificFineTuneRequest + params: SpecificFineTuneRequest, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task) => { - return client.fineTunes.cancel(params.fineTuneId, { idempotencyKey: task.idempotencyKey }); + return client.fineTunes.cancel(params.fineTuneId, { + idempotencyKey: task.idempotencyKey, + ...options, + }); }, { name: "Cancel fine tune", @@ -111,12 +121,13 @@ export class FineTunes { listEvents( key: IntegrationTaskKey, - params: SpecificFineTuneRequest + params: SpecificFineTuneRequest, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client, task) => { - return client.fineTunes.listEvents(params.fineTuneId, { stream: false }); + return client.fineTunes.listEvents(params.fineTuneId, { stream: false, ...options }); }, { name: "List fine tune events", @@ -142,7 +153,8 @@ export class FineTunes { */ create: ( key: IntegrationTaskKey, - params: OpenAI.FineTuning.JobCreateParams + params: OpenAI.FineTuning.JobCreateParams, + options: OpenAIRequestOptions = {} ): Promise => { let properties = [ { @@ -168,7 +180,10 @@ export class FineTunes { return this.runTask( key, async (client, task) => { - return client.fineTuning.jobs.create(params, { idempotencyKey: task.idempotencyKey }); + return client.fineTuning.jobs.create(params, { + idempotencyKey: task.idempotencyKey, + ...options, + }); }, { name: "Create Fine Tuning Job", @@ -180,12 +195,13 @@ export class FineTunes { retrieve: ( key: IntegrationTaskKey, - params: { id: string } + params: { id: string }, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task) => { - return client.fineTuning.jobs.retrieve(params.id); + return client.fineTuning.jobs.retrieve(params.id, options); }, { name: "Retrieve Fine Tuning Job", @@ -202,12 +218,16 @@ export class FineTunes { cancel: ( key: IntegrationTaskKey, - params: { id: string } + params: { id: string }, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task) => { - return client.fineTuning.jobs.cancel(params.id, { idempotencyKey: task.idempotencyKey }); + return client.fineTuning.jobs.cancel(params.id, { + idempotencyKey: task.idempotencyKey, + ...options, + }); }, { name: "Cancel Fine Tuning Job", @@ -224,12 +244,13 @@ export class FineTunes { listEvents: ( key: IntegrationTaskKey, - params: { id: string } + params: { id: string }, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task) => { - const response = await client.fineTuning.jobs.listEvents(params.id); + const response = await client.fineTuning.jobs.listEvents(params.id, options); return response.data; }, { @@ -247,12 +268,13 @@ export class FineTunes { list: ( key: IntegrationTaskKey, - params: OpenAI.FineTuning.JobListParams + params: OpenAI.FineTuning.JobListParams, + options: OpenAIRequestOptions = {} ): Promise => { return this.runTask( key, async (client, task) => { - const response = await client.fineTuning.jobs.list(params); + const response = await client.fineTuning.jobs.list(params, options); return response.data; }, diff --git a/integrations/openai/src/images.ts b/integrations/openai/src/images.ts index ce87876cf..0a2b839d4 100644 --- a/integrations/openai/src/images.ts +++ b/integrations/openai/src/images.ts @@ -1,8 +1,8 @@ -import { fileFromUrl, truncate } from "@trigger.dev/integration-kit"; +import { fileFromUrl } from "@trigger.dev/integration-kit"; import { IntegrationTaskKey, Prettify } from "@trigger.dev/sdk"; import OpenAI from "openai"; import { OpenAIRunTask } from "./index"; -import { createTaskUsageProperties } from "./taskUtils"; +import { OpenAIRequestOptions } from "./types"; export type CreateImageEditRequest = { image: string | File; @@ -31,7 +31,8 @@ export class Images { generate( key: IntegrationTaskKey, - params: Prettify + params: Prettify, + options: OpenAIRequestOptions = {} ): Promise { let properties = [ { @@ -64,7 +65,7 @@ export class Images { return this.runTask( key, async (client, task) => { - return client.images.generate(params, { idempotencyKey: task.idempotencyKey }); + return client.images.generate(params, { idempotencyKey: task.idempotencyKey, ...options }); }, { name: "Create image", @@ -76,7 +77,8 @@ export class Images { edit( key: IntegrationTaskKey, - params: CreateImageEditRequest + params: CreateImageEditRequest, + options: OpenAIRequestOptions = {} ): Promise { let properties = []; @@ -131,7 +133,7 @@ export class Images { response_format: params.response_format, user: params.user, }, - { idempotencyKey: task.idempotencyKey } + { idempotencyKey: task.idempotencyKey, ...options } ); return response; @@ -146,7 +148,8 @@ export class Images { createVariation( key: IntegrationTaskKey, - params: CreateImageVariationRequest + params: CreateImageVariationRequest, + options: OpenAIRequestOptions = {} ): Promise { let properties = []; @@ -193,7 +196,7 @@ export class Images { response_format: params.response_format, user: params.user, }, - { idempotencyKey: task.idempotencyKey } + { idempotencyKey: task.idempotencyKey, ...options } ); return response; diff --git a/integrations/openai/src/index.ts b/integrations/openai/src/index.ts index 89fe9dc21..ce20ccacf 100644 --- a/integrations/openai/src/index.ts +++ b/integrations/openai/src/index.ts @@ -56,6 +56,9 @@ export class OpenAI implements TriggerIntegration { apiKey: options.apiKey, organization: options.organization, baseURL: options.baseURL, + defaultHeaders: options.defaultHeaders, + defaultQuery: options.defaultQuery, + maxRetries: 0, }); } @@ -79,6 +82,9 @@ export class OpenAI implements TriggerIntegration { apiKey, organization: this._options.organization, baseURL: this._options.baseURL ?? "https://api.openai.com/v1", + defaultHeaders: this._options.defaultHeaders, + defaultQuery: this._options.defaultQuery, + maxRetries: 0, }); return openai; } @@ -120,11 +126,11 @@ export class OpenAI implements TriggerIntegration { } get completions() { - return new Completions(this.runTask.bind(this)); + return new Completions(this.runTask.bind(this), this._options); } get chat() { - return new Chat(this.runTask.bind(this)); + return new Chat(this.runTask.bind(this), this._options); } get edits() { diff --git a/integrations/openai/src/models.ts b/integrations/openai/src/models.ts index 7f1d37282..cc0afc057 100644 --- a/integrations/openai/src/models.ts +++ b/integrations/openai/src/models.ts @@ -2,6 +2,7 @@ import { IntegrationTaskKey } from "@trigger.dev/sdk"; import { Model } from "openai/resources"; import { OpenAIRunTask } from "./index"; import OpenAI from "openai"; +import { OpenAIRequestOptions } from "./types"; type DeleteFineTunedModelRequest = { fineTunedModelId: string; @@ -13,11 +14,15 @@ export class Models { this.runTask = runTask; } - retrieve(key: IntegrationTaskKey, params: { model: string }): Promise { + retrieve( + key: IntegrationTaskKey, + params: { model: string }, + options: OpenAIRequestOptions = {} + ): Promise { return this.runTask( key, async (client) => { - return client.models.retrieve(params.model); + return client.models.retrieve(params.model, options); }, { name: "Retrieve model", @@ -32,11 +37,11 @@ export class Models { ); } - list(key: IntegrationTaskKey): Promise { + list(key: IntegrationTaskKey, options: OpenAIRequestOptions = {}): Promise { return this.runTask( key, async (client) => { - const result = await client.models.list(); + const result = await client.models.list(options); return result.data; }, { @@ -48,12 +53,13 @@ export class Models { delete( key: IntegrationTaskKey, - params: DeleteFineTunedModelRequest + params: DeleteFineTunedModelRequest, + options: OpenAIRequestOptions = {} ): Promise { return this.runTask( key, async (client) => { - return client.models.del(params.fineTunedModelId); + return client.models.del(params.fineTunedModelId, options); }, { name: "Delete fine tune model", diff --git a/integrations/openai/src/taskUtils.ts b/integrations/openai/src/taskUtils.ts index 9dca5a858..4689f5b4e 100644 --- a/integrations/openai/src/taskUtils.ts +++ b/integrations/openai/src/taskUtils.ts @@ -1,4 +1,6 @@ import OpenAI from "openai"; +import { OpenAIRequestOptions } from "./types"; +import { redactString } from "@trigger.dev/sdk"; export function createTaskUsageProperties( usage: OpenAI.Completions.CompletionUsage | OpenAI.CreateEmbeddingResponse.Usage | undefined @@ -30,3 +32,80 @@ export function createTaskUsageProperties( export function onTaskError(error: unknown) { return; } + +export function createBackgroundFetchUrl( + client: OpenAI, + endpoint: string, + defaultQuery: OpenAIRequestOptions["query"] = {}, + options: OpenAIRequestOptions = {} +) { + let baseURL = client.baseURL ?? "https://api.openai.com/v1"; + if (baseURL.endsWith("/")) { + baseURL = baseURL.slice(0, -1); + } + + const path = options.path ?? endpoint; + + const url = new URL(`${baseURL}${path}`); + + if (options.query) { + for (const [key, value] of Object.entries(options.query)) { + if (value !== undefined) { + url.searchParams.append(key, value); + } + } + } + + for (const [key, value] of Object.entries(defaultQuery)) { + if (value !== undefined) { + url.searchParams.append(key, value); + } else { + url.searchParams.delete(key); + } + } + + return url.href; +} + +export function createBackgroundFetchHeaders( + client: OpenAI, + idempotencyKey: string, + defaultHeaders: OpenAIRequestOptions["headers"] = {}, + options: OpenAIRequestOptions = {} +) { + return { + "Content-Type": "application/json", + Authorization: redactString`Bearer ${client.apiKey}`, + ...(client.organization ? { "OpenAI-Organization": client.organization } : {}), + "Idempotency-Key": options.idempotencyKey ?? idempotencyKey, + ...(options.headers ?? {}), + ...defaultHeaders, + }; +} + +export const backgroundTaskRetries = { + "500-599": { + strategy: "backoff", + limit: 5, + minTimeoutInMs: 1000, + maxTimeoutInMs: 30000, + factor: 1.8, + randomize: true, + }, + "429": { + strategy: "backoff", + limit: 10, + minTimeoutInMs: 1000, + maxTimeoutInMs: 60000, + factor: 2, + randomize: true, + }, + "408-409": { + strategy: "backoff", + limit: 3, + minTimeoutInMs: 1000, + maxTimeoutInMs: 60000, + factor: 2, + randomize: true, + }, +} as const; diff --git a/integrations/openai/src/types.ts b/integrations/openai/src/types.ts index 2dad32871..fabc24d71 100644 --- a/integrations/openai/src/types.ts +++ b/integrations/openai/src/types.ts @@ -1,9 +1,37 @@ +type OpenAIHTTPMethod = "get" | "post" | "put" | "patch" | "delete"; +type OpenAIHeaders = Record; +type OpenAIQuery = Record; + export type OpenAIIntegrationOptions = { id: string; apiKey?: string; organization?: string; baseURL?: string; icon?: string; + + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `undefined` or `null` in request options. + */ + defaultHeaders?: OpenAIHeaders; + + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: OpenAIQuery; }; export type OpenAIIntegrationAuth = Omit; + +export type OpenAIRequestOptions = { + method?: OpenAIHTTPMethod; + query?: OpenAIQuery; + path?: string; + headers?: OpenAIHeaders; + idempotencyKey?: string; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b35f0510..828bd5444 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -457,18 +457,20 @@ importers: '@trigger.dev/sdk': workspace:^2.2.1 '@trigger.dev/tsconfig': workspace:* '@types/node': '18' - openai: ^4.2.0 + openai: ^4.13.0 rimraf: ^3.0.2 tsup: ^6.5.0 + typescript: ^4.9.4 dependencies: '@trigger.dev/integration-kit': link:../../packages/integration-kit '@trigger.dev/sdk': link:../../packages/trigger-sdk - openai: 4.2.0 + openai: 4.13.0 devDependencies: '@trigger.dev/tsconfig': link:../../config-packages/tsconfig '@types/node': 18.15.13 rimraf: 3.0.2 - tsup: 6.6.3 + tsup: 6.6.3_typescript@4.9.5 + typescript: 4.9.5 integrations/plain: specifiers: @@ -25374,8 +25376,8 @@ packages: is-docker: 2.2.1 is-wsl: 2.2.0 - /openai/4.2.0: - resolution: {integrity: sha512-zfvpO2eITIxIjTG8T6Cek7NB2dMvP/LW0TRUJ4P9E8+qbBNKw00DrtfF64b+fAV2+wUYCVyynT6iSycJ//TtbA==} + /openai/4.13.0: + resolution: {integrity: sha512-EPqHcB0got9cXDZmQae1KytgA4YWtTnUc7tV8hlahZtcO70DMa4kiaXoxnutj9lwmeKQO7ntG+6pmXtrCMejuQ==} hasBin: true dependencies: '@types/node': 18.17.1 @@ -25386,6 +25388,7 @@ packages: form-data-encoder: 1.7.2 formdata-node: 4.4.1 node-fetch: 2.6.12 + web-streams-polyfill: 3.2.1 transitivePeerDependencies: - encoding dev: false diff --git a/references/job-catalog/src/openai.ts b/references/job-catalog/src/openai.ts index e8e96f5f6..e7b016191 100644 --- a/references/job-catalog/src/openai.ts +++ b/references/job-catalog/src/openai.ts @@ -13,6 +13,7 @@ export const client = new TriggerClient({ const openai = new OpenAI({ id: "openai", apiKey: process.env["OPENAI_API_KEY"]!, + defaultHeaders: { "user-agent": "trigger.dev job-catalog reference 1.0" }, }); client.defineJob({ @@ -34,7 +35,7 @@ client.defineJob({ }); } - await io.openai.backgroundCreateChatCompletion("background-chat-completion", { + await io.openai.chat.completions.backgroundCreate("background-chat-completion", { model: "gpt-3.5-turbo", messages: [ { @@ -44,7 +45,7 @@ client.defineJob({ ], }); - await io.openai.createChatCompletion("chat-completion", { + await io.openai.chat.completions.create("chat-completion", { model: "gpt-3.5-turbo", messages: [ { @@ -54,7 +55,12 @@ client.defineJob({ ], }); - await io.openai.createCompletion("completion", { + await io.openai.completions.backgroundCreate("background-completion", { + model: "text-davinci-003", + prompt: "Create a good programming joke about Tasks", + }); + + await io.openai.completions.create("completion", { model: "text-davinci-003", prompt: "Create a good programming joke about Tasks", }); @@ -112,4 +118,54 @@ client.defineJob({ }, }); +const azureOpenAI = new OpenAI({ + id: "azure-openai", + apiKey: process.env["AZURE_API_KEY"]!, + icon: "brand-azure", + baseURL: "https://my-resource.openai.azure.com/openai/deployments/my-gpt35-16k-deployment", + defaultQuery: { "api-version": "2023-06-01-preview" }, + defaultHeaders: { "api-key": process.env["AZURE_API_KEY"] }, +}); + +client.defineJob({ + id: "azure-tasks", + name: "azure Tasks", + version: "0.0.1", + trigger: eventTrigger({ + name: "azure.tasks", + }), + integrations: { + azureOpenAI, + }, + run: async (payload, io, ctx) => { + await io.azureOpenAI.chat.completions.create( + "chat-completion", + { + model: "my-gpt35-16k-deployment", + messages: [ + { + role: "user", + content: "Create a good programming joke about background jobs", + }, + ], + }, + { + headers: { + "User-Agent": "Trigger.dev", + }, + } + ); + + await io.azureOpenAI.chat.completions.backgroundCreate("background-chat-completion", { + model: "my-gpt35-16k-deployment", + messages: [ + { + role: "user", + content: "If you were a programming language, what would you be and why?", + }, + ], + }); + }, +}); + createExpressServer(client);