Skip to content

AI scenarios

Reasoning

Bit.BlazorUI.AI Scripted transport

Model thinking, shown in its own collapsed panel and kept out of the answer, the copy, and the next prompt.

Live demo

Ask the starter question: the model thinks out loud first, then answers.

\n**Reasoning before the answer**: ```razor @implements IAsyncDisposable
``` ```csharp private readonly BitAiChatSession session = new(AiDemoTransports.Reasoning()); private readonly string[] suggestions = ["What does a round trip actually cost?"]; public ValueTask DisposeAsync() => session.DisposeAsync(); ``` `AiDemoTransports.cs`: ```csharp // AiScriptedTransport and AiScript are the demo's helpers - see the Basic chat scenario. public static IBitAiTransport Reasoning() => new AiScriptedTransport((request, token) => AiScript.Stream(token, async yielder => { await yielder(new BitAiMessageStartedEvent()); // Reasoning first: a word at a time, as BitAiReasoningDeltaEvents. const string thinking = "The user is asking about the cost of a round trip. I should separate the fixed cost of " + "the connection from the per-token cost, and give a number rather than an adjective."; // A word every 70 ms: about two seconds of thinking, long enough to watch the panel stream open before it // collapses into "Thought for ...". await foreach (var evt in AiScript.Think(thinking, 70, token)) await yielder(evt); await AiScript.Pause(250, token); // Then the answer, as ordinary text deltas. const string answer = """ Two costs are worth separating. **Connection setup** is roughly constant: ... """; await foreach (var evt in AiScript.Write(answer, 4, 12, token)) await yielder(evt); await yielder(AiScript.Usage(request, answer)); await yielder(new BitAiMessageCompletedEvent(BitAiFinishReason.Stop)); })); // AiScript.Think: one reasoning delta per word. public static async IAsyncEnumerable Think(string text, int delayMs = 10, [EnumeratorCancellation] CancellationToken cancellationToken = default) { foreach (var word in text.Split(' ')) { await Task.Delay(delayMs, cancellationToken); yield return new BitAiReasoningDeltaEvent(word + " "); } } ```

How it works

Reasoning arrives as BitAiReasoningDeltaEvent and becomes a BitAiReasoningPart. Because it is a part of its own rather than text with a label, it can be collapsed, timed, excluded from the copy button, and left out of the plain-text projection of the conversation sent back to the provider on the next turn (IBitAiMessage.GetText() skips it). A provider that needs its reasoning replayed on a later turn sends an opaque Signature with the delta, which the part keeps.

The transport here streams the reasoning a word at a time, then the answer as ordinary text deltas. Nothing says where the thinking ends: the first part of the answer completes the reasoning part, as a BitAiPartCompletedEvent for it would. The panel is open while the model thinks and folds itself away once the answer starts, with the time it took in its header. BitAiUiOptions.CollapseReasoning turns the folding off; a reader who opens or closes the panel themselves keeps it the way they left it.

Components used

Feedback

Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.