-
-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenAI structured outputs support #1307
Comments
By the way, OpenAI understands only understands the |
Also, about the The Therefore, if you want to contribute to Here is the code filling the typia/src/programmers/internal/llm_schema_object.ts Lines 98 to 121 in 8edeef5
|
I haven't found any info about if OpenAI supporting |
For example, the OpenAPI SDK has the following unit tests: https://github.com/openai/openai-python/blob/aeaed488352274a9ca86c834eeb618d732989518/tests/lib/test_pydantic.py#L65 no references to oneOf unfortunately. |
How about the other models? In the Google Gemini case, it is using the OpenAPI v3.0.3 specified JSON schema, but not supporting
OpenAI, it sometimes looks like using OpenAPI v3.1, and sometimes v3.0. It supports mixed-in types embodied by |
To support LLM function calling feature exactly, I should separate the providers like below.
|
@antoniomdk If you send an PR about Also, about the manipulating specific LLM provider's schema, I'll prepare the major update. It would be |
@samchon That sounds great! I think the LLM-specific separation makes a lot of sense. I'll send a PR for |
Related to LLM structured outputs, I find that when prompting I often want to use the jsdoc comment for a type in the prompt. Can typia add a misc method for returning the jsdoc string of a particular type. Using |
@antoniomdk, @bradleat https://github.com/samchon/openapi/blob/v2.0/src/structures/IChatGptSchema.ts I'm preparing the OpenAI dedicated schema type as Here is the type, and I'll test it by using the ChatGPT API, and considering below things.
If you want to experience it earlier, install npm install typia@next |
Here is an example of the currently considering Source Codeimport {
ChatGptTypeChecker,
IChatGptSchema,
ILlmApplication,
} from "@samchon/openapi";
import typia, { tags } from "typia";
const app: ILlmApplication<"chatgpt"> = typia.llm.application<
BbsArticleController,
"chatgpt"
>({
separate: (schema: IChatGptSchema) =>
ChatGptTypeChecker.isString(schema) &&
schema.contentMediaType !== undefined,
});
console.log(app);
interface BbsArticleController {
/**
* Create a new article.
*
* Writes a new article and archives it into the DB.
*
* @param input Information of the article to create
* @returns Newly created article
*/
create(input: IBbsArticle.ICreate): Promise<IBbsArticle>;
/**
* Update an article.
*
* Updates an article with new content.
*
* @param id Target article's {@link IBbsArticle.id}
* @param input New content to update
*/
update(
id: string & tags.Format<"uuid">,
input: IBbsArticle.IUpdate,
): Promise<void>;
/**
* Erase an article.
*
* Erases an article from the DB.
*
* @param id Target article's {@link IBbsArticle.id}
*/
erase(id: string & tags.Format<"uuid">): Promise<void>;
}
/**
* Article entity.
*
* `IBbsArticle` is an entity representing an article in the BBS (Bulletin Board System).
*/
interface IBbsArticle extends IBbsArticle.ICreate {
/**
* Primary Key.
*/
id: string & tags.Format<"uuid">;
/**
* Creation time of the article.
*/
created_at: string & tags.Format<"date-time">;
/**
* Last updated time of the article.
*/
updated_at: string & tags.Format<"date-time">;
}
namespace IBbsArticle {
/**
* Information of the article to create.
*/
export interface ICreate {
/**
* Title of the article.
*
* Representative title of the article.
*/
title: string;
/**
* Content body.
*
* Content body of the article writtn in the markdown format.
*/
body: string;
/**
* Thumbnail image URI.
*
* Thumbnail image URI which can represent the article.
*
* If configured as `null`, it means that no thumbnail image in the article.
*/
thumbnail:
| null
| (string & tags.Format<"uri"> & tags.ContentMediaType<"image/*">);
}
/**
* Information of the article to update.
*
* Only the filled properties will be updated.
*/
export type IUpdate = Partial<ICreate>;
} Compiled Codeimport * as __typia_transform__llmApplicationFinalize from "typia/lib/internal/_llmApplicationFinalize.js";
import { ChatGptTypeChecker } from "@samchon/openapi";
import typia from "typia";
const app = (() => {
const app = {
model: "chatgpt",
functions: [
{
name: "create",
parameters: [
{
$ref: "#/$defs/IBbsArticle.ICreate",
description: "Information of the article to create",
$defs: {
"IBbsArticle.ICreate": {
type: "object",
properties: {
title: {
type: "string",
title: "Title of the article",
description:
"Title of the article.\n\nRepresentative title of the article.",
},
body: {
type: "string",
title: "Content body",
description:
"Content body.\n\nContent body of the article writtn in the markdown format.",
},
thumbnail: {
oneOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
title: "Thumbnail image URI",
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
},
},
required: ["title", "body", "thumbnail"],
description: "Information of the article to create.",
additionalProperties: false,
},
},
},
],
output: {
$ref: "#/$defs/IBbsArticle",
description: "Newly created article",
$defs: {
IBbsArticle: {
type: "object",
properties: {
id: {
type: "string",
format: "uuid",
title: "Primary Key",
description: "Primary Key.",
},
created_at: {
type: "string",
format: "date-time",
title: "Creation time of the article",
description: "Creation time of the article.",
},
updated_at: {
type: "string",
format: "date-time",
title: "Last updated time of the article",
description: "Last updated time of the article.",
},
title: {
type: "string",
title: "Title of the article",
description:
"Title of the article.\n\nRepresentative title of the article.",
},
body: {
type: "string",
title: "Content body",
description:
"Content body.\n\nContent body of the article writtn in the markdown format.",
},
thumbnail: {
oneOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
title: "Thumbnail image URI",
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
},
},
required: [
"id",
"created_at",
"updated_at",
"title",
"body",
"thumbnail",
],
description:
"Article entity.\n\n`IBbsArticle` is an entity representing an article in the BBS (Bulletin Board System).",
additionalProperties: false,
},
},
},
description:
"Create a new article.\n\nWrites a new article and archives it into the DB.",
},
{
name: "update",
parameters: [
{
type: "string",
format: "uuid",
description: "Target article's ",
},
{
$ref: "#/$defs/PartialIBbsArticle.ICreate",
description: "New content to update",
$defs: {
"PartialIBbsArticle.ICreate": {
type: "object",
properties: {
title: {
type: "string",
title: "Title of the article",
description:
"Title of the article.\n\nRepresentative title of the article.",
},
body: {
type: "string",
title: "Content body",
description:
"Content body.\n\nContent body of the article writtn in the markdown format.",
},
thumbnail: {
oneOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
title: "Thumbnail image URI",
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
},
},
description: "Make all properties in T optional",
additionalProperties: false,
},
},
},
],
description:
"Update an article.\n\nUpdates an article with new content.",
},
{
name: "erase",
parameters: [
{
type: "string",
format: "uuid",
description: "Target article's ",
},
],
description: "Erase an article.\n\nErases an article from the DB.",
},
],
options: {
separate: null,
},
};
__typia_transform__llmApplicationFinalize._llmApplicationFinalize(app, {
separate: (schema) =>
ChatGptTypeChecker.isString(schema) &&
schema.contentMediaType !== undefined,
});
return app;
})();
console.log(app); |
Feature Request
I've been working with
typia.llm.schema
for a while and it has been extremely helpful in generating JSON schemas to call LLMs from TS types. However, the new structured outputs API of OpenAI has some limitations in the type of schemas it can take.In particular
nullable
is not been taken into account. So it'd be great if we could map typesX | null
toanyOf
. Maybe introducing a new flag to thetypia.llm.schema
function.Also, for types that don't extend from Record, we should mark
[additionalProperties to false](https://platform.openai.com/docs/guides/structured-outputs/additionalproperties-false-must-always-be-set-in-objects)
.I can contribute to this feature, but I may need some pointers for code references to start.
The text was updated successfully, but these errors were encountered: