(message: string, userId: string)
| 15 | export const humanToCronSupported = typeof env.OPENAI_API_KEY === "string"; |
| 16 | |
| 17 | export async function humanToCron(message: string, userId: string): Promise<HumanToCronResult> { |
| 18 | if (!humanToCronSupported) { |
| 19 | return { |
| 20 | isValid: false, |
| 21 | error: "OpenAI API key is not set", |
| 22 | }; |
| 23 | } |
| 24 | |
| 25 | const openai = new OpenAI({ apiKey: env.OPENAI_API_KEY }); |
| 26 | |
| 27 | const completion = await openai.chat.completions.create({ |
| 28 | model: "gpt-3.5-turbo-1106", |
| 29 | user: userId, |
| 30 | messages: [ |
| 31 | { |
| 32 | role: "system", |
| 33 | content: `You are a helpful assistant who will turn nautral language into a valid CRON expresion. |
| 34 | |
| 35 | The version of CRON that we use is an extension of the minimal. |
| 36 | |
| 37 | * * * * * |
| 38 | ┬ ┬ ┬ ┬ ┬ |
| 39 | │ │ │ │ | |
| 40 | │ │ │ │ └ day of week (0 - 7, 1L - 7L) (0 or 7 is Sun) |
| 41 | │ │ │ └───── month (1 - 12) |
| 42 | │ │ └────────── day of month (1 - 31, L) |
| 43 | │ └─────────────── hour (0 - 23) |
| 44 | └──────────────────── minute (0 - 59) |
| 45 | |
| 46 | Supports mixed use of ranges and range increments (W character not supported currently). See tests for examples. |
| 47 | |
| 48 | Return JSON in one of these formats, putting in the correct data where you see <THE CRON EXPRESSION> and <ERROR MESSAGE DESCRIBING WHY IT'S NOT VALID>: |
| 49 | 1. If it's valid: { "isValid": true, "cron": "<THE CRON EXPRESSION>" } |
| 50 | 2. If it's not possible to make a valid CRON expression: { "isValid": false, "error": "<ERROR MESSAGE DESCRIBING WHY IT'S NOT VALID>"}`, |
| 51 | }, |
| 52 | { |
| 53 | role: "user", |
| 54 | content: `What is a valid CRON expression for this: ${message}`, |
| 55 | }, |
| 56 | ], |
| 57 | response_format: { type: "json_object" }, |
| 58 | }); |
| 59 | |
| 60 | if (!completion.choices[0]?.message.content) { |
| 61 | return { |
| 62 | isValid: false, |
| 63 | error: "No response from OpenAI", |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | logger.debug("OpenAI response", { |
| 68 | completion, |
| 69 | }); |
| 70 | |
| 71 | const jsonResponse = safeJsonParse(completion.choices[0].message.content); |
| 72 | |
| 73 | if (!jsonResponse) { |
| 74 | return { |
no test coverage detected
searching dependent graphs…