Skip to content

Add demo for structured outputs#375

Merged
awaescher merged 1 commit intomainfrom
auto-releasenotes
Mar 17, 2026
Merged

Add demo for structured outputs#375
awaescher merged 1 commit intomainfrom
auto-releasenotes

Conversation

@awaescher
Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings March 5, 2026 07:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a "Structured outputs" demo to the OllamaSharp console demo application. It demonstrates how to constrain a model's response to a predefined JSON schema by having the user enter a dish name and receiving a fully structured RecipeSchema object in return. The ToggleThink logic in OllamaConsole was also refactored to extract a new SetThink(object?) helper method.

Changes:

  • A new StructuredOutputConsole demo that sends a JSON schema as the format parameter and renders the result as a formatted recipe card.
  • A new SetThink(object? value) helper method extracted from the existing ToggleThink logic in OllamaConsole.
  • A new "Structured outputs" entry added to the main demo selection menu in Program.cs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
demo/Demos/StructuredOutputConsole.cs New demo class: prompts for a dish name, calls the model with a JSON schema format constraint, streams the output, pretty-prints JSON, and renders a recipe card.
demo/OllamaConsole.cs Extracted SetThink(object?) from ToggleThink to allow callers to set think mode to a specific value programmatically.
demo/Program.cs Added "Structured outputs" to the menu and switch statement to route to the new demo.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +20
private static readonly JsonSerializerOptions SERIALIZER_OPTIONS = new()
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field SERIALIZER_OPTIONS uses UPPER_CASE naming, which in this codebase is reserved for const fields (e.g., MULTILINE_OPEN, MULTILINE_CLOSE, START_NEW_COMMAND). This is a private static readonly field, not a constant. It should follow the naming convention for non-const fields. The src project uses _camelCase for private readonly statics (e.g., _schemaTransformCache in AbstractionMapper.cs). Renaming to _serializerOptions would align with the established convention.

Copilot uses AI. Check for mistakes.
}

/// <summary>
/// Toggles the think mode between null, false, and true.
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML doc comment for SetThink reads "Toggles the think mode between null, false, and true." — this is a copy-paste of the ToggleThink summary and does not accurately describe what this method does. SetThink sets think mode to a specific value passed as the argument, rather than cycling through states. The summary should instead reflect the actual behavior, for example: "Sets the think mode to the specified value and prints the updated state to the console."

Suggested change
/// Toggles the think mode between null, false, and true.
/// Sets the think mode to the specified value and prints the updated state to the console.

Copilot uses AI. Check for mistakes.
AnsiConsole.WriteLine();

Ollama.SelectedModel = await SelectModel("Select a model you want to use:");
SetThink(new ThinkValue(false));
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetThink accepts object? and internally wraps it with new ThinkValue(value). The call SetThink(new ThinkValue(false)) therefore double-wraps the value: a ThinkValue struct is passed as object?, boxed, and then re-parsed by the ThinkValue(object? value) constructor via bool.TryParse(value.ToString(), ...). While the end result happens to be semantically correct (because ThinkValue(false).ToString() returns "false" which parses correctly), the intent is clearer and simpler as SetThink(false), which uses the existing implicit conversion from bool to ThinkValue.

Suggested change
SetThink(new ThinkValue(false));
SetThink(false);

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +36
SetThink(new ThinkValue(false));

if (string.IsNullOrEmpty(Ollama.SelectedModel))
return;

Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetThink(new ThinkValue(false)) is called before the guard that checks whether a model was selected (line 34). If the user presses "back" at the model selection prompt, Ollama.SelectedModel will be empty and the demo exits immediately, but "Think mode is false." will still be printed to the console. This produces a confusing message when the user never actually entered the demo. The SetThink call should be moved to after the empty-model guard, consistent with the flow in other demos that do not emit side-effect output before checking a precondition.

Suggested change
SetThink(new ThinkValue(false));
if (string.IsNullOrEmpty(Ollama.SelectedModel))
return;
if (string.IsNullOrEmpty(Ollama.SelectedModel))
return;
SetThink(new ThinkValue(false));

Copilot uses AI. Check for mistakes.
@awaescher awaescher merged commit a87dfee into main Mar 17, 2026
4 checks passed
This was referenced Mar 18, 2026
This was referenced Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants