{"id":22138260,"url":"https://github.com/jamesmcroft/openai-structured-outputs-with-dotnet","last_synced_at":"2026-03-04T04:02:52.816Z","repository":{"id":264950295,"uuid":"867512418","full_name":"jamesmcroft/openai-structured-outputs-with-dotnet","owner":"jamesmcroft","description":"Experiment using JsonSchemaExporter in .NET 9 to improve developer experience with OpenAI's Structured Outputs","archived":false,"fork":false,"pushed_at":"2025-03-19T20:35:20.000Z","size":29,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-29T21:59:18.751Z","etag":null,"topics":["azure","azure-openai","dotnet","openai","structured-outputs"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesmcroft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-04T07:53:39.000Z","updated_at":"2025-03-31T17:39:50.000Z","dependencies_parsed_at":"2025-04-10T11:41:32.438Z","dependency_job_id":"6bbafc5b-3b88-4f5c-8f17-370eaf8b40e1","html_url":"https://github.com/jamesmcroft/openai-structured-outputs-with-dotnet","commit_stats":null,"previous_names":["jamesmcroft/openai-structured-outputs-with-dotnet"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jamesmcroft/openai-structured-outputs-with-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmcroft%2Fopenai-structured-outputs-with-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmcroft%2Fopenai-structured-outputs-with-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmcroft%2Fopenai-structured-outputs-with-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmcroft%2Fopenai-structured-outputs-with-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesmcroft","download_url":"https://codeload.github.com/jamesmcroft/openai-structured-outputs-with-dotnet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmcroft%2Fopenai-structured-outputs-with-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30071670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T03:25:38.285Z","status":"ssl_error","status_checked_at":"2026-03-04T03:25:05.086Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-openai","dotnet","openai","structured-outputs"],"created_at":"2024-12-01T20:09:15.325Z","updated_at":"2026-03-04T04:02:52.804Z","avatar_url":"https://github.com/jamesmcroft.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Azure OpenAI GPT-4o Structured Outputs with .NET\n\nThe goal of this sample is to demonstrate how to leverage the Azure OpenAI GPT-4o structured outputs feature by generating valid OpenAI JSON schemas for a given Type in .NET.\n\n## How it works\n\n\u003e [!IMPORTANT]\n\u003e The original vision was to leverage the `JsonSchemaExporter` in .NET 9 to generate JSON schemas. However, the generated schemas are not directly compatible with the OpenAI SDK. The current implementation is a workaround to generate valid schemas for structured outputs.\n\nThe [`OpenAIJsonSchema` class](./src/StructuredOutputs/OpenAIJsonSchema.cs) provides a mechanism to generate a valid OpenAI JSON schema for any given model Type. The class uses reflection to traverse the properties of the model Type and generate the schema based on the property types.\n\nThe [`StructuredOutputsExtensions` class](./src/StructuredOutputs/StructuredOutputsExtensions.cs) provides a generic `CreateJsonSchemaFormat` method that can be passed a model object type and will return the `ChatResponseFormat` object that can be used by the OpenAI SDK. This method uses the `OpenAIJsonSchema.For` method to generate the schema for the model object type.\n\nIn addition to the generic `CreateJsonSchemaFormat` method, a generic `CompleteChat` and `CompleteChatAsync` extension is provided for the `ChatClient` that will return a wrapped `ChatCompletion` object as [`ParsedChatCompletion`](./src/StructuredOutputs/ParsedChatCompletion.cs) that includes a `Parsed` property containing the deserialized model object.\n\n### Example\n\n```csharp\nclass Family\n{\n    public List\u003cPerson\u003e Parents { get; set; }\n    public List\u003cPerson\u003e? Children { get; set; }\n\n    class Person\n    {\n        public string Name { get; set; }\n        public int Age { get; set; }\n    }\n}\n\nChatCompletionOptions options = new()\n{\n    ResponseFormat = StructuredOutputsExtensions.CreateJsonSchemaFormat\u003cFamily\u003e(\"family\", jsonSchemaIsStrict: true),\n    MaxOutputTokenCount = 4096,\n    Temperature = 0.1f,\n    TopP = 0.1f\n};\n\nList\u003cChatMessage\u003e messages =\n[\n    new SystemChatMessage(\"You are an AI assistant that creates families.\"),\n    new UserChatMessage(\"Create a family with 2 parents and 2 children.\")\n];\n\nParsedChatCompletion\u003cFamily?\u003e completion = chatClient.CompleteChat(messages, options);\nFamily? family = completion.Parsed;\n```\n\nYou can also provide descriptions for schema properties by using the `DescriptionAttribute`:\n\n```csharp\nclass Person\n{\n    [Description(\"The name of the person.\")]\n    public string Name { get; set; }\n\n    [Description(\"The age of the person.\")]\n    public int Age { get; set; }\n}\n```\n\nThese are included in the generated schema:\n\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"Name\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the person.\"\n    },\n    \"Age\": {\n      \"type\": \"integer\",\n      \"description\": \"The age of the person.\"\n    }\n  }\n}\n```\n\n## Running the sample\n\n- Install the latest [**.NET 9 SDK**](https://dotnet.microsoft.com/en-us/download/dotnet/9.0).\n- Install [**PowerShell Core**](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell).\n- Install the [**Azure CLI**](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli).\n- Install [**Visual Studio Code**](https://code.visualstudio.com/).\n\nAdditionally, you will require:\n\n- An Azure subscription. If you don't have an Azure subscription, create an [account](https://azure.microsoft.com/en-us/).\n\nTo setup a local development environment, follow these steps:\n\n\u003e [!NOTE]\n\u003e For the most optimal sample experience, it is recommended to deploy the necessary infrastructure in a region that supports `GPT-4o` version `2024-08-06`. Find out more about region availability for the [`GPT-4o`](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models#standard-and-global-standard-deployment-model-quota) model.\n\n```pwsh\naz login\n\n./Setup-Environment.ps1 -DeploymentName \u003cUniqueDeploymentName\u003e -Location \u003cAzureRegion\u003e -SkipInfrastructure $false\n```\n\nThe script will deploy the following resources to your Azure subscription:\n\n- [**Azure AI Services**](https://learn.microsoft.com/en-us/azure/ai-services/what-are-ai-services), a managed service for all Azure AI Services, including Azure OpenAI.\n  - **Note**: GPT-4o will be deployed as Global Standard with 10K TPM quota allocation. This can be adjusted based on your quota availability in the [main.bicep](./infra/main.bicep) file.\n\n\u003e [!NOTE]\n\u003e Resources are secured by default with Microsoft Entra ID using Azure RBAC. Your user client ID will be added with the necessary least-privilege roles to access the resources created.\n\nAfter the script completes, a `.env` file will be crated in the `src/StructuredOutputs` folder and you can run the sample project by following these steps:\n\n```pwsh\ncd src/StructuredOutputs\ndotnet run\n```\n\n## Resources\n\n- [Azure OpenAI GPT-4o Structured Outputs Supported Schemas and Limitations](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/structured-outputs?tabs=python-secure#supported-schemas-and-limitations)\n- [How to use chat completions with structured outputs in OpenAI .NET SDK](https://github.com/openai/openai-dotnet?tab=readme-ov-file#how-to-use-chat-completions-with-structured-outputs)\n- [.NET 9 JSON Schema Exporter](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/libraries#jsonschemaexporter)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmcroft%2Fopenai-structured-outputs-with-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesmcroft%2Fopenai-structured-outputs-with-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmcroft%2Fopenai-structured-outputs-with-dotnet/lists"}