Skip to content

Commit ec69d49

Browse files
committed
OpenAI: Added support for structured outputs in Chat action
1 parent 6c012d0 commit ec69d49

File tree

5 files changed

+64
-9
lines changed

5 files changed

+64
-9
lines changed

components/openai/actions/chat/chat.mjs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import constants from "../../common/constants.mjs";
55
export default {
66
...common,
77
name: "Chat",
8-
version: "0.1.11",
8+
version: "0.1.12",
99
key: "openai-chat",
1010
description: "The Chat API, using the `gpt-3.5-turbo` or `gpt-4` model. [See the documentation](https://platform.openai.com/docs/api-reference/chat)",
1111
type: "action",
@@ -43,13 +43,27 @@ export default {
4343
responseFormat: {
4444
type: "string",
4545
label: "Response Format",
46-
description: "Specify the format that the model must output. [Setting to `json_object` guarantees the message the model generates is valid JSON](https://platform.openai.com/docs/api-reference/chat/create#chat-create-response_format). Defaults to `text`",
47-
options: constants.CHAT_RESPONSE_FORMATS,
46+
description: "Specify the format that the model must output. \n- **Text** (default): Returns unstructured text output.\n- **JSON Object**: Ensures the model's output is a valid JSON object.\n- **JSON Schema** (GPT-4o and later): Enables you to define a specific structure for the model's output using a JSON schema. Supported with models `gpt-4o-2024-08-06` and later, and `gpt-4o-mini-2024-07-18` and later.",
47+
options: Object.values(constants.CHAT_RESPONSE_FORMAT),
4848
optional: true,
4949
default: "text",
50+
reloadProps: true,
5051
},
5152
...common.props,
5253
},
54+
additionalProps() {
55+
const { responseFormat } = this;
56+
if (responseFormat !== constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) {
57+
return {};
58+
}
59+
return {
60+
jsonSchema: {
61+
type: "string",
62+
label: "JSON Schema",
63+
description: "Define the schema that the model's output must adhere to. [See the documentation here](https://platform.openai.com/docs/guides/structured-outputs/supported-schemas).",
64+
},
65+
};
66+
},
5367
async run({ $ }) {
5468
const args = this._getChatArgs();
5569

components/openai/actions/common/common.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { ConfigurationError } from "@pipedream/platform";
2+
import constants from "../../common/constants.mjs";
3+
import { parse } from "../../common/helpers.mjs";
24

35
const CHAT_DOCS_MESSAGE_FORMAT_URL = "https://platform.openai.com/docs/guides/chat/introduction";
46

@@ -148,9 +150,17 @@ export default {
148150

149151
const responseFormat = {};
150152

153+
const jsonSchemaObj =
154+
this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value
155+
? {
156+
json_schema: parse(this.jsonSchema),
157+
}
158+
: {};
159+
151160
if (this.modelId != "gpt-4-vision-preview") {
152161
responseFormat["response_format"] = {
153162
type: this.responseFormat,
163+
...jsonSchemaObj,
154164
};
155165
}
156166

components/openai/common/constants.mjs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,20 @@ const AUDIO_RESPONSE_FORMATS = [
4545
"pcm",
4646
];
4747

48-
const CHAT_RESPONSE_FORMATS = [
49-
"text",
50-
"json_object",
51-
];
48+
const CHAT_RESPONSE_FORMAT = {
49+
TEXT: {
50+
label: "Text",
51+
value: "text",
52+
},
53+
JSON_OBJECT: {
54+
label: "JSON Object",
55+
value: "json_object",
56+
},
57+
JSON_SCHEMA: {
58+
label: "JSON Schema",
59+
value: "json_schema",
60+
},
61+
};
5262

5363
const IMAGE_RESPONSE_FORMATS = [
5464
{
@@ -162,7 +172,7 @@ export default {
162172
IMAGE_MODELS,
163173
MODERATION_MODELS,
164174
AUDIO_RESPONSE_FORMATS,
165-
CHAT_RESPONSE_FORMATS,
175+
CHAT_RESPONSE_FORMAT,
166176
IMAGE_RESPONSE_FORMATS,
167177
USER_OPTIONS,
168178
ORDER_OPTIONS,

components/openai/common/helpers.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ConfigurationError } from "@pipedream/platform";
2+
13
export function parseToolsArray(arr) {
24
if (!arr) return undefined;
35
return arr.map((value) => {
@@ -16,3 +18,22 @@ export function parseToolsArray(arr) {
1618
}
1719
});
1820
}
21+
22+
function emptyStrToUndefined(value) {
23+
const trimmed = typeof(value) === "string" && value.trim();
24+
return trimmed === ""
25+
? undefined
26+
: value;
27+
}
28+
29+
export function parse(value) {
30+
const valueToParse = emptyStrToUndefined(value);
31+
if (typeof(valueToParse) === "object" || valueToParse === undefined) {
32+
return valueToParse;
33+
}
34+
try {
35+
return JSON.parse(valueToParse);
36+
} catch (e) {
37+
throw new ConfigurationError("Make sure the schema contains a valid JSON object.");
38+
}
39+
}

components/openai/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/openai",
3-
"version": "0.5.4",
3+
"version": "0.5.5",
44
"description": "Pipedream OpenAI Components",
55
"main": "openai.app.mjs",
66
"keywords": [

0 commit comments

Comments
 (0)