@trigger.dev/openai: Adding additional assistant tasks

This commit is contained in:
Eric Allam
2023-11-28 22:48:31 +00:00
parent 4dc46cbbe4
commit ca05d5f603
9 changed files with 391 additions and 38 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/openai": patch
---
Adding additional assistant tasks
+1
View File
@@ -60,6 +60,7 @@ const EnvironmentSchema = z.object({
REDIS_PORT: z.coerce.number().optional(),
REDIS_USERNAME: z.string().optional(),
REDIS_PASSWORD: z.string().optional(),
REDIS_TLS_DISABLED: z.string().optional(),
DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT: z.coerce.number().int().default(10),
DEFAULT_DEV_ENV_EXECUTION_ATTEMPTS: z.coerce.number().int().positive().default(1),
@@ -397,7 +397,7 @@ function getRateLimiter() {
username: env.REDIS_USERNAME,
password: env.REDIS_PASSWORD,
enableAutoPipelining: true,
tls: {}
...(env.REDIS_TLS_DISABLED === "true" ? {} : { tls: {} })
},
defaultConcurrency: env.DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT,
});
+63 -1
View File
@@ -33,6 +33,54 @@ const assistant = await io.openai.beta.assistants.create("create-assistant", {
});
```
### `update()`
Update an assistant. [Official OpenAI Docs](https://platform.openai.com/docs/api-reference/assistants/modifyAssistant)
```ts example.ts
const file = await io.openai.files.createAndWaitForProcessing("upload-file", {
purpose: "assistants",
file: fs.createReadStream("./fixtures/mydata.csv"),
});
const assistantId = "asst_abc123";
const assistant = await io.openai.beta.assistants.update("update-assistant", assistantId, {
file_ids: [file.id], // add a file to the assistant
});
```
### `list()`
List assistants. [Official OpenAI Docs](https://platform.openai.com/docs/api-reference/assistants/listAssistants)
```ts example.ts
const assistants = await io.openai.beta.assistants.list("list");
// with pagination
const assistants = await io.openai.beta.assistants.list("list", {
limit: 10,
order: "desc",
after: "asst_abc123",
});
```
### `retrieve()`
Retrieve an assistant. [Official OpenAI Docs](https://platform.openai.com/docs/api-reference/assistants/getAssistant)
```ts example.ts
const assistant = await io.openai.beta.assistants.retrieve("get-assistant", "asst_abc123");
```
### `del()`
Delete an assistant. [Official OpenAI Docs](https://platform.openai.com/docs/api-reference/assistants/deleteAssistant)
```ts example.ts
const deletedAssistant = await io.openai.beta.assistants.del("delete-assistant", "asst_abc123");
```
## Threads
Create threads that assistants can interact with. [Official OpenAI docs](https://platform.openai.com/docs/api-reference/threads/createThread)
@@ -132,12 +180,26 @@ Create messages within threads. [Official OpenAI docs](https://platform.openai.c
### `list()`
List all messages in a thread.
List messages in a thread.
```ts example.ts
const messages = await io.openai.beta.threads.messages.list("list-messages", "thread_abc123");
// with pagination
const messages = await io.openai.beta.threads.messages.list("list-messages", "thread_abc123", {
limit: 10,
order: "desc",
after: "message_abc123",
});
```
If you want to list all messages in a thread, you can use the `listAll()` helper:
```ts example.ts
const messages = await io.openai.beta.threads.messages.listAll("list-messages", "thread_abc123");
```
This will automatically paginate through all messages in the thread and return them as a single array.
### `create()`
Create a message. [Official OpenAI Docs](https://platform.openai.com/docs/api-reference/messages/createMessage)
+171 -2
View File
@@ -2,13 +2,13 @@ import { IntegrationTaskKey, Prettify } from "@trigger.dev/sdk";
import { OpenAIRunTask } from "./index";
import { OpenAIIntegrationOptions, OpenAIRequestOptions } from "./types";
import OpenAI from "openai";
import { createTaskOutputProperties, handleOpenAIError } from "./taskUtils";
import { createTaskOutputProperties, handleOpenAIError, isRequestOptions } from "./taskUtils";
export class Assistants {
constructor(
private runTask: OpenAIRunTask,
private options: OpenAIIntegrationOptions
) {}
) { }
async create(
key: IntegrationTaskKey,
@@ -54,4 +54,173 @@ export class Assistants {
handleOpenAIError
);
}
async update(
key: IntegrationTaskKey,
id: string,
params: Prettify<OpenAI.Beta.AssistantUpdateParams>,
options: OpenAIRequestOptions = {}
): Promise<OpenAI.Beta.Assistant> {
return this.runTask(
key,
async (client, task) => {
const { data, response } = await client.beta.assistants
.update(id, params, {
idempotencyKey: task.idempotencyKey,
...options,
})
.withResponse();
const outputProperties = createTaskOutputProperties(undefined, response.headers);
task.outputProperties = [
...(outputProperties ?? []),
{
label: "assistantId",
text: data.id,
},
];
return data;
},
{
name: "Update Assistant",
params,
properties: [
...(params.model ? [{ label: "model", text: params.model }] : []),
...(params.name ? [{ label: "name", text: params.name }] : []),
...(params.file_ids && params.file_ids.length > 0
? [{ label: "files", text: params.file_ids.join(", ") }]
: []),
],
},
handleOpenAIError
);
}
list(
key: IntegrationTaskKey,
params?: Prettify<OpenAI.Beta.AssistantListParams>,
options?: OpenAIRequestOptions,
): Promise<OpenAI.Beta.Assistant[]>;
list(
key: IntegrationTaskKey,
options?: OpenAIRequestOptions,
): Promise<OpenAI.Beta.Assistant[]>;
async list(
key: IntegrationTaskKey,
params: Prettify<OpenAI.Beta.AssistantListParams> | OpenAIRequestOptions = {},
options: OpenAIRequestOptions | undefined = undefined
): Promise<OpenAI.Beta.Assistant[]> {
return this.runTask(
key,
async (client, task) => {
if (isRequestOptions(params)) {
const { data, response } = await client.beta.assistants
.list({
idempotencyKey: task.idempotencyKey,
...params,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return data.data;
}
const { data, response } = await client.beta.assistants
.list(params, {
idempotencyKey: task.idempotencyKey,
...options,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return data.data;
},
{
name: "List Assistants",
params,
properties: !isRequestOptions(params) ? [
...(params.before ? [{ label: "before", text: params.before }] : []),
...(params.order ? [{ label: "order", text: params.order }] : []),
...(params.after ? [{ label: "after", text: params.after }] : []),
...(params.limit ? [{ label: "limit", text: String(params.limit) }] : []),
] : [],
},
handleOpenAIError
);
}
async del(
key: IntegrationTaskKey,
id: string,
options: OpenAIRequestOptions = {}
): Promise<OpenAI.Beta.AssistantDeleted> {
return this.runTask(
key,
async (client, task) => {
const { data, response } = await client.beta.assistants
.del(id, {
idempotencyKey: task.idempotencyKey,
...options,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return data;
},
{
name: "Delete Assistant",
params: {
id,
},
properties: [
{
label: "assistantId",
text: id,
},
],
},
handleOpenAIError
);
}
async retrieve(
key: IntegrationTaskKey,
id: string,
options: OpenAIRequestOptions = {}
): Promise<OpenAI.Beta.Assistant> {
return this.runTask(
key,
async (client, task) => {
const { data, response } = await client.beta.assistants
.retrieve(id, {
idempotencyKey: task.idempotencyKey,
...options,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return data;
},
{
name: "Retrieve Assistant",
params: {
id,
},
properties: [
{
label: "assistantId",
text: id,
},
],
},
handleOpenAIError
);
}
}
+54 -25
View File
@@ -60,11 +60,11 @@ function createTaskUsageProperties(
},
...("completion_tokens" in usage
? [
{
label: "Completion Usage",
text: String(usage.completion_tokens),
},
]
{
label: "Completion Usage",
text: String(usage.completion_tokens),
},
]
: []),
];
}
@@ -83,35 +83,35 @@ function createTaskRateLimitProperties(headers: Headers | undefined) {
return [
...(remainingRequests
? [
{
label: "Remaining Requests",
text: remainingRequests ?? "Unknown",
},
]
{
label: "Remaining Requests",
text: remainingRequests ?? "Unknown",
},
]
: []),
...(resetRequests
? [
{
label: "Reset Requests",
text: resetRequests ?? "Unknown",
},
]
{
label: "Reset Requests",
text: resetRequests ?? "Unknown",
},
]
: []),
...(remainingTokens
? [
{
label: "Remaining Tokens",
text: remainingTokens ?? "Unknown",
},
]
{
label: "Remaining Tokens",
text: remainingTokens ?? "Unknown",
},
]
: []),
...(resetTokens
? [
{
label: "Reset Tokens",
text: resetTokens ?? "Unknown",
},
]
{
label: "Reset Tokens",
text: resetTokens ?? "Unknown",
},
]
: []),
];
}
@@ -282,3 +282,32 @@ export const backgroundTaskRetries: FetchRetryOptions = {
randomize: true,
},
};
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const requestOptionsKeys: KeysEnum<OpenAIRequestOptions> = {
method: true,
path: true,
query: true,
headers: true,
idempotencyKey: true,
};
export const isRequestOptions = (obj: unknown): obj is OpenAIRequestOptions => {
return (
typeof obj === 'object' &&
obj !== null &&
!isEmptyObj(obj) &&
Object.keys(obj).every((k) => hasOwn(requestOptionsKeys, k))
);
};
function isEmptyObj(obj: Object | null | undefined): boolean {
if (!obj) return true;
for (const _k in obj) return false;
return true;
}
function hasOwn(obj: Object, key: string): boolean {
return Object.prototype.hasOwnProperty.call(obj, key);
}
+64 -8
View File
@@ -7,6 +7,7 @@ import {
createBackgroundFetchUrl,
createTaskOutputProperties,
handleOpenAIError,
isRequestOptions,
} from "./taskUtils";
import { RunSubmitToolOutputsParams } from "openai/resources/beta/threads/runs/runs";
import { ThreadUpdateParams } from "openai/resources/beta/threads/threads";
@@ -15,7 +16,7 @@ export class Threads {
constructor(
private runTask: OpenAIRunTask,
private options: OpenAIIntegrationOptions
) {}
) { }
/**
* Create a thread and run it in one task.
@@ -261,7 +262,7 @@ class Runs {
constructor(
private runTask: OpenAIRunTask,
private options: OpenAIIntegrationOptions
) {}
) { }
/**
* Creates a run and waits for it to complete by polling in the background.
@@ -551,15 +552,70 @@ class Messages {
constructor(
private runTask: OpenAIRunTask,
private options: OpenAIIntegrationOptions
) {}
) { }
/**
* Returns messages for a given thread.
*/
list(
key: IntegrationTaskKey,
threadId: string,
params?: Prettify<OpenAI.Beta.Threads.MessageListParams>,
options?: OpenAIRequestOptions
): Promise<OpenAI.Beta.Threads.ThreadMessage[]>
list(
key: IntegrationTaskKey,
threadId: string,
options?: OpenAIRequestOptions
): Promise<OpenAI.Beta.Threads.ThreadMessage[]>
async list(
key: IntegrationTaskKey,
threadId: string,
params: Prettify<OpenAI.Beta.AssistantListParams> | OpenAIRequestOptions = {},
options: OpenAIRequestOptions | undefined = undefined
): Promise<OpenAI.Beta.Threads.ThreadMessage[]> {
return this.runTask(
key,
async (client, task, io) => {
if (isRequestOptions(params)) {
const { data: page, response } = await client.beta.threads.messages
.list(threadId, {
idempotencyKey: task.idempotencyKey,
...params,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return page.data;
}
const { data: page, response } = await client.beta.threads.messages
.list(threadId, params, {
idempotencyKey: task.idempotencyKey,
...options,
})
.withResponse();
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
return page.data;
},
{
name: "List Messages",
properties: [{ label: "threadId", text: threadId }],
},
handleOpenAIError
);
}
/**
* Returns all messages for a given thread.
*/
async list(
async listAll(
key: IntegrationTaskKey,
threadId: string,
options: OpenAIRequestOptions = {}
options: OpenAIRequestOptions = {},
): Promise<OpenAI.Beta.Threads.ThreadMessage[]> {
return this.runTask(
key,
@@ -573,8 +629,8 @@ class Messages {
const allMessages = [];
for await (const fineTuningJob of page) {
allMessages.push(fineTuningJob);
for await (const message of page) {
allMessages.push(message);
}
task.outputProperties = createTaskOutputProperties(undefined, response.headers);
@@ -582,7 +638,7 @@ class Messages {
return allMessages;
},
{
name: "List Messages",
name: "List All Messages",
properties: [{ label: "threadId", text: threadId }],
},
handleOpenAIError
+1 -1
View File
@@ -34,4 +34,4 @@ export type OpenAIRequestOptions = {
path?: string;
headers?: OpenAIHeaders;
idempotencyKey?: string;
};
};
+31
View File
@@ -228,6 +228,37 @@ client.defineJob({
},
});
client.defineJob({
id: "openai-manage-assistant",
name: "OpenAI GPT Manage Assistant",
version: "0.0.1",
trigger: invokeTrigger({
schema: z.object({
assistantId: z.string().optional(),
}),
}),
integrations: {
openai,
},
run: async (payload, io, ctx) => {
const assistants = await io.openai.beta.assistants.list("list", {
limit: 10
});
if (payload.assistantId) {
await io.openai.beta.assistants.retrieve("retrieve", payload.assistantId);
await io.openai.beta.assistants.update("update", payload.assistantId, {
name: "Updated name",
});
await io.openai.beta.assistants.del("delete", payload.assistantId);
}
for (const assistant of assistants) {
await io.openai.beta.assistants.del(`delete ${assistant.id}`, assistant.id);
}
},
});
client.defineJob({
id: "openai-use-assistant",
name: "OpenAI GPT Use Assistant",