<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Deepak Battini on Medium]]></title>
        <description><![CDATA[Stories by Deepak Battini on Medium]]></description>
        <link>https://medium.com/@deepakbattini?source=rss-2bcce0e423a9------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*NSCbfYAAUXr2Tp2O.</url>
            <title>Stories by Deepak Battini on Medium</title>
            <link>https://medium.com/@deepakbattini?source=rss-2bcce0e423a9------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 02 Aug 2026 16:59:38 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@deepakbattini/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 3: Building the Agent]]></title>
            <link>https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-3-building-the-agent-c5991bf0b5c2?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/c5991bf0b5c2</guid>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Fri, 13 Feb 2026 09:16:00 GMT</pubDate>
            <atom:updated>2026-02-14T19:38:01.137Z</atom:updated>
            <content:encoded><![CDATA[<ul><li><strong>Part 1</strong>: <a href="https://medium.com/@deepakbattini/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-1-foundations-0c054f2c9485">The AI SDK — providers, models, messages, and generating text</a></li><li><strong>Part 2</strong>: <a href="https://medium.com/@deepakbattini/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-2-building-tools-fd78a9ff261d">Building Tools — teaching the model to interact with the real world</a></li><li><strong>Part 3</strong> (this article): Building the Agent — the agentic loop that ties everything together</li></ul><h3>The Missing Piece</h3><p>We have a model (Part 1) and tools (Part 2). But right now, using them requires manual orchestration — call the model, check if it wants tools, execute them, feed results back, call the model again, check again… This is tedious and error-prone. What if the model needs 15 tool calls to scaffold an entire React app?</p><p>We need an <strong>agentic loop</strong>: an automated cycle that handles the entire call-tools-respond flow. This is the core of every AI coding agent — Cursor, Claude Code, and Copilot all have one. Here’s what ours looks like:</p><pre>User message<br>    │<br>    ▼<br>┌──────────────────────────────────┐<br>│          AGENTIC LOOP            │<br>│                                  │<br>│  Call model with history + tools │<br>│           │                      │<br>│           ▼                      │<br>│    ┌─ Tool calls? ──┐           │<br>│    │ Yes             │ No        │<br>│    ▼                 ▼           │<br>│  Execute tools   Return text    │<br>│  Feed results    ───► EXIT      │<br>│  back to model                  │<br>│    │                             │<br>│    └──── loop ◄─────┘           │<br>└──────────────────────────────────┘</pre><p>Let’s build it.</p><h3>Typed Events — What the Loop Emits</h3><p>Our agent loop is a producer: it yields events as things happen. The consumer (your CLI or UI) decides how to display them. Using C# IAsyncEnumerable and a typed event hierarchy makes this clean.</p><pre>namespace AiSdk.Agent;<br>public abstract record AgentEvent;<br>public record ToolCallEvent(ToolCall ToolCall) : AgentEvent;<br>public record ToolResultEvent(string ToolName, string ToolCallId, string Result) : AgentEvent;<br>public record TextResponseEvent(string Text) : AgentEvent;<br>public record StatusEvent(string Message) : AgentEvent;<br>public record UsageEvent(Usage Usage, int CumulativeTokens) : AgentEvent;</pre><p>Why typed events instead of IAsyncEnumerable&lt;object&gt;?</p><ul><li><strong>Pattern matching</strong> — switch (ev) { case ToolCallEvent e: ... } is clean and type-safe</li><li><strong>Exhaustiveness</strong> — the compiler warns if you miss a case</li><li><strong>Discoverability</strong> — IntelliSense shows you exactly what events exist</li><li><strong>No casting</strong> — each event type carries its specific data</li></ul><h3>Agent Options — Configuration</h3><p>The agent needs some knobs:</p><pre>public record AgentOptions<br>{<br>    /// The system prompt that defines the agent&#39;s behavior.<br>    public required string SystemPrompt { get; init; }<br>    /// Max model calls per user message. Prevents runaway loops. Default: 50.<br>    public int MaxIterations { get; init; } = 50;<br>    /// Summarize conversation when cumulative tokens exceed this. Default: 128K.<br>    public int? TokenSummarizationThreshold { get; init; } = 128_000;<br>    /// Messages to keep when summarizing. Default: 6.<br>    public int MessagesToKeepOnSummarize { get; init; } = 6;<br>    /// Custom summarization prompt (or null for built-in default).<br>    public string? SummarizationSystemPrompt { get; init; }<br>    /// Default model parameters (Temperature, MaxTokens, etc.).<br>    public AgentModelCallDefaults? ModelCallDefaults { get; init; }<br>}</pre><p>The system prompt is required because it defines the agent&#39;s entire personality and capabilities. Everything else has sensible defaults.</p><h3>The Agent Class</h3><p>Here’s the full implementation. It’s ~160 lines — let’s walk through it section by section.</p><h3>Constructor</h3><pre>using AiSdk.Abstractions;<br>using AiSdk.Tools;<br>namespace AiSdk.Agent;<br>public class Agent<br>{<br>    private readonly ILanguageModel _model;<br>    private readonly ToolRegistry _tools;<br>    private readonly AgentOptions _options;<br>    private readonly List&lt;Message&gt; _conversationHistory = new();<br>    public Agent(ILanguageModel model, ToolRegistry tools, AgentOptions options)<br>    {<br>        _model = model;<br>        _tools = tools;<br>        _options = options;<br>        // Seed the conversation with the system prompt<br>        _conversationHistory.Add(new Message(MessageRole.System, options.SystemPrompt));<br>    }<br>    public IReadOnlyList&lt;Message&gt; ConversationHistory =&gt; _conversationHistory.AsReadOnly();<br>}</pre><p>Three dependencies, all injected:</p><ul><li><strong>ILanguageModel</strong> — any provider (OpenAI, Anthropic, Azure, etc.)</li><li><strong>ToolRegistry</strong> — any set of tools</li><li><strong>AgentOptions</strong> — configuration including the system prompt</li></ul><p>The conversation history is seeded with the system prompt and persists across SendMessageAsync calls, giving the model memory of the entire session.</p><h3>The Agentic Loop</h3><p>This is the core method:</p><pre>public async IAsyncEnumerable&lt;AgentEvent&gt; SendMessageAsync(<br>    string input,<br>    [EnumeratorCancellation] CancellationToken ct = default)<br>{<br>    _conversationHistory.Add(new Message(MessageRole.User, input));<br>    int cumulativeTokens = 0;<br>    for (int iteration = 0; iteration &lt; _options.MaxIterations; iteration++)<br>    {<br>        // 1. Check if we need to summarize (approaching context limits)<br>        if (_options.TokenSummarizationThreshold is int threshold<br>            &amp;&amp; cumulativeTokens &gt; threshold)<br>        {<br>            yield return new StatusEvent(&quot;Summarizing conversation to free up context...&quot;);<br>            await SummarizeConversationAsync(ct);<br>            cumulativeTokens = 0;<br>            yield return new StatusEvent(&quot;Context compressed - continuing&quot;);<br>        }<br>        // 2. Call the model<br>        var callOptions = BuildCallOptions();<br>        var result = await _model.GenerateAsync(callOptions, ct);<br>        // 3. Track token usage<br>        cumulativeTokens += result.Usage?.TotalTokens ?? 0;<br>        if (result.Usage is not null)<br>            yield return new UsageEvent(result.Usage, cumulativeTokens);<br>        // 4. Handle the response<br>        if (result.FinishReason == FinishReason.ToolCalls &amp;&amp; result.ToolCalls?.Count &gt; 0)<br>        {<br>            // Model wants to call tools - execute them and continue the loop<br>            foreach (var toolCall in result.ToolCalls)<br>                yield return new ToolCallEvent(toolCall);<br>            var toolResultsSb = new StringBuilder();<br>            foreach (var toolCall in result.ToolCalls)<br>            {<br>                var toolResult = await _tools.ExecuteAsync(<br>                    toolCall.ToolName, toolCall.Arguments, ct);<br>                toolResultsSb.AppendLine(<br>                    $&quot;&lt;tool_result name=\&quot;{toolCall.ToolName}\&quot; &quot; +<br>                    $&quot;id=\&quot;{toolCall.ToolCallId}\&quot;&gt;&quot;);<br>                toolResultsSb.AppendLine(toolResult);<br>                toolResultsSb.AppendLine(&quot;&lt;/tool_result&gt;&quot;);<br>                yield return new ToolResultEvent(<br>                    toolCall.ToolName, toolCall.ToolCallId, toolResult);<br>            }<br>            // Add to conversation history and loop<br>            if (!string.IsNullOrEmpty(result.Text))<br>                _conversationHistory.Add(new Message(MessageRole.Assistant, result.Text));<br>            _conversationHistory.Add(new Message(MessageRole.User, toolResultsSb.ToString()));<br>        }<br>        else<br>        {<br>            // Final text response - we&#39;re done<br>            var text = result.Text ?? &quot;&quot;;<br>            _conversationHistory.Add(new Message(MessageRole.Assistant, text));<br>            yield return new TextResponseEvent(text);<br>            yield break;<br>        }<br>    }<br>    yield return new StatusEvent($&quot;Reached maximum iterations ({_options.MaxIterations})&quot;);<br>}</pre><p>Let’s break down the key decisions:</p><p><strong>Why </strong><strong>IAsyncEnumerable?</strong> Because the agent produces events over time — it might make 10 tool calls before producing a final response. IAsyncEnumerable&lt;AgentEvent&gt; lets the consumer process events as they happen (show tool progress in real time) instead of waiting for everything to finish.</p><p><strong>Why feed tool results as User messages?</strong> Most LLM APIs expect the conversation to alternate between user/assistant roles. Tool results are information the model needs to continue, so they go in as user messages wrapped in &lt;tool_result&gt; XML tags. The model reads these and decides what to do next.</p><p><strong>Why </strong><strong>MaxIterations?</strong> Without a limit, a confused model could loop forever — calling tools that fail, retrying, failing again. 50 iterations is generous enough for complex tasks but prevents infinite loops.</p><p><strong>Why track cumulative tokens?</strong> The conversation grows with every tool call and result. A single “build me a React app” prompt might generate 100K+ tokens of tool calls and results. When we approach the model’s context limit, we summarize to avoid errors.</p><h3>Conversation Summarization</h3><p>When the conversation gets too long, the agent compresses it:</p><pre>private async Task SummarizeConversationAsync(CancellationToken ct)<br>{<br>    int recentToKeep = _options.MessagesToKeepOnSummarize;<br>    if (_conversationHistory.Count &lt;= recentToKeep + 2)<br>        return;<br>    // Split: [system prompt] [old messages to summarize] [recent messages to keep]<br>    int summarizeEnd = _conversationHistory.Count - recentToKeep;<br>    var toSummarize = _conversationHistory.GetRange(1, summarizeEnd - 1);<br>    // Build text representation of messages to summarize<br>    var historyText = new StringBuilder();<br>    foreach (var msg in toSummarize)<br>    {<br>        var content = msg.Content;<br>        if (content.Length &gt; 2000)<br>            content = content[..2000] + &quot;...[truncated]&quot;;<br>        historyText.AppendLine($&quot;[{msg.Role}]: {content}&quot;);<br>    }<br>    // Ask the model to summarize<br>    var summarizeMessages = new List&lt;Message&gt;<br>    {<br>        new(MessageRole.System, SummarizationPrompt),<br>        new(MessageRole.User, $&quot;Summarize this conversation:\n\n{historyText}&quot;)<br>    };<br>    var result = await _model.GenerateAsync(new LanguageModelCallOptions<br>    {<br>        Messages = summarizeMessages<br>    }, ct);<br>    // Rebuild: [system prompt] [summary] [recent messages]<br>    var recentMessages = _conversationHistory<br>        .GetRange(summarizeEnd, _conversationHistory.Count - summarizeEnd);<br>    _conversationHistory.Clear();<br>    _conversationHistory.Add(new Message(MessageRole.System, _options.SystemPrompt));<br>    _conversationHistory.Add(new Message(MessageRole.Assistant,<br>        $&quot;[Conversation Summary]\n{result.Text}&quot;));<br>    _conversationHistory.AddRange(recentMessages);<br>}</pre><p>The strategy: keep the system prompt, keep the last N messages (for immediate context), and replace everything in between with a summary. The model gets enough context to continue working without re-reading files.</p><h3>Putting It All Together — The Vibe Coder</h3><p>Now we wire everything up. The application-specific code is tiny — just credentials, system prompt, and a UI loop.</p><h3>The Wrapper (BlzAgent.cs)</h3><pre>using AiSdk.Agent;<br>using AiSdk.Providers.Azure;<br>using AiSdk.Tools;<br><br>public class BlzAgent<br>{<br>    private readonly Agent _agent;<br>    public BlzAgent(string? workingDirectory = null)<br>    {<br>        var workDir = workingDirectory ?? Directory.GetCurrentDirectory();<br>        var model = AzureOpenAIProvider.CreateChatModel(<br>            deploymentName: &quot;gpt-4o&quot;,<br>            endpoint: &quot;https://my-resource.openai.azure.com&quot;,<br>            apiKey: &quot;your-key&quot;<br>        );<br>        var tools = VibeCodingTools.CreateRegistry(workDir);<br>        _agent = new Agent(model, tools, new AgentOptions<br>        {<br>            SystemPrompt = $&quot;&quot;&quot;<br>                You are an expert software engineer.<br>                Your working directory is: {workDir}<br>                CRITICAL RULES:<br>                - ALWAYS use tools to create and modify files. Never just output code as text.<br>                - Use read_file before edit_file so you know the exact content to replace.<br>                - Use bash to run builds, tests, and other commands.<br>                - Use absolute paths based on the working directory.<br>                &quot;&quot;&quot;<br>        });<br>    }<br>    public IAsyncEnumerable&lt;AgentEvent&gt; SendMessage(string input)<br>        =&gt; _agent.SendMessageAsync(input);<br>    public void ResetConversation()<br>        =&gt; _agent.ResetConversation();<br>}</pre><p>That’s it. ~30 lines. The generic Agent class handles the entire agentic loop. BlzAgent is just configuration: which provider, which tools, what system prompt.</p><h3>The CLI (Program.cs)</h3><pre>using AiSdk.Agent;<br>var agent = new BlzAgent(args.Length &gt; 0 ? args[0] : Directory.GetCurrentDirectory());<br>Console.WriteLine(&quot;Type your request. /reset to clear, /quit to exit.\n&quot;);<br>while (true)<br>{<br>    Console.ForegroundColor = ConsoleColor.Green;<br>    Console.Write(&quot;You &gt; &quot;);<br>    Console.ResetColor();<br>    var input = Console.ReadLine();<br>    if (string.IsNullOrWhiteSpace(input)) continue;<br>    if (input.Trim().Equals(&quot;/quit&quot;, StringComparison.OrdinalIgnoreCase)) break;<br>    if (input.Trim().Equals(&quot;/reset&quot;, StringComparison.OrdinalIgnoreCase))<br>    {<br>        agent.ResetConversation();<br>        Console.WriteLine(&quot;  [Conversation reset]\n&quot;);<br>        continue;<br>    }<br>    Console.WriteLine();<br>    try<br>    {<br>        await foreach (var ev in agent.SendMessage(input))<br>        {<br>            switch (ev)<br>            {<br>                case ToolCallEvent { ToolCall: var tc }:<br>                    Console.ForegroundColor = ConsoleColor.DarkCyan;<br>                    Console.Write($&quot;  &gt; {tc.ToolName}&quot;);<br>                    Console.ResetColor();<br>                    var args = tc.Arguments.RootElement.GetRawText();<br>                    if (args.Length &gt; 120) args = args[..120] + &quot;...&quot;;<br>                    Console.WriteLine($&quot;  {args}&quot;);<br>                    break;<br>                case ToolResultEvent { Result: var result }:<br>                    Console.ForegroundColor = ConsoleColor.DarkGray;<br>                    var preview = result.ReplaceLineEndings(&quot; &quot;);<br>                    if (preview.Length &gt; 150) preview = preview[..150] + &quot;...&quot;;<br>                    Console.WriteLine($&quot;    OK {preview}&quot;);<br>                    Console.ResetColor();<br>                    break;<br>                case TextResponseEvent { Text: var text }:<br>                    Console.ForegroundColor = ConsoleColor.White;<br>                    Console.Write(text);<br>                    Console.ResetColor();<br>                    break;<br>                case StatusEvent { Message: var msg }:<br>                    Console.ForegroundColor = ConsoleColor.Yellow;<br>                    Console.WriteLine($&quot;  [{msg}]&quot;);<br>                    Console.ResetColor();<br>                    break;<br>                case UsageEvent:<br>                    break; // Silently ignore<br>            }<br>        }<br>    }<br>    catch (Exception ex)<br>    {<br>        Console.ForegroundColor = ConsoleColor.Red;<br>        Console.WriteLine($&quot;\n  [Error] {ex.Message}&quot;);<br>        Console.ResetColor();<br>    }<br>    Console.WriteLine(&quot;\n&quot; + new string(&#39;-&#39;, 60) + &quot;\n&quot;);<br>}</pre><p>The pattern matching on AgentEvent subtypes makes the display logic clean and extensible. Want to add a token counter? Handle UsageEvent. Want to log tool calls? Handle ToolCallEvent. The agent doesn&#39;t care what you do with the events.</p><h3>Swapping Providers — The Payoff</h3><p>Because Agent takes ILanguageModel, switching providers is a one-line change:</p><pre>// Azure OpenAI<br>var model = AzureOpenAIProvider.CreateChatModel(&quot;gpt-4o&quot;, endpoint, apiKey);<br>// OpenAI directly<br>var model = OpenAIProvider.CreateChatModel(&quot;gpt-4o&quot;, apiKey: &quot;sk-...&quot;);<br>// Anthropic Claude<br>var model = AnthropicProvider.CreateChatModel(&quot;claude-3-5-sonnet-20241022&quot;, apiKey: &quot;sk-ant-...&quot;);\<br>// Google Gemini<br>var model = GoogleProvider.CreateChatModel(&quot;gemini-pro&quot;, apiKey: &quot;...&quot;);<br>// Groq (fast inference)<br>var model = GroqProvider.CreateChatModel(&quot;llama-3.1-70b-versatile&quot;, apiKey: &quot;...&quot;);</pre><p>Same tools. Same agent. Same CLI. Different brain.</p><h3>Architecture Summary</h3><p>Here’s the final architecture, showing how everything connects:</p><pre>┌─────────────────────────────────────────────────┐<br>│ Program.cs (CLI)                                │<br>│   Handles user I/O, displays AgentEvents        │<br>└────────────────────┬────────────────────────────┘<br>                     │ IAsyncEnumerable&lt;AgentEvent&gt;<br>                     │<br>┌────────────────────▼────────────────────────────┐<br>│ BlzAgent (thin wrapper)                         │<br>│   Azure credentials + system prompt             │<br>│   Creates: model, tools, Agent                  │<br>└────────────────────┬────────────────────────────┘<br>                     │<br>┌────────────────────▼────────────────────────────┐<br>│ Agent (AiSdk.Agent)               GENERIC       │<br>│   Agentic loop: model → tools → loop            │<br>│   Conversation history + summarization          │<br>│   Emits: ToolCallEvent, ToolResultEvent,        │<br>│          TextResponseEvent, StatusEvent,         │<br>│          UsageEvent                              │<br>├─────────────────┬───────────────────────────────┤<br>│ ILanguageModel  │  ToolRegistry                 │<br>│ (any provider)  │  (any tools)                  │<br>└─────────────────┴───────────────────────────────┘</pre><p>The generic layer (Agent, AgentEvent, AgentOptions, ToolRegistry) lives in the AI SDK NuGet package. Your application only provides:</p><ol><li><strong>A provider</strong> — which LLM to use</li><li><strong>Tools</strong> — what the agent can do</li><li><strong>A system prompt</strong> — how the agent should behave</li><li><strong>A UI</strong> — how to display events</li></ol><h3>What You Could Build Next</h3><p>This foundation opens up a lot of possibilities:</p><ul><li><strong>Streaming responses</strong> — Use model.StreamAsync() in the agent loop for real-time token-by-token text output</li><li><strong>Tool confirmation</strong> — Emit a ToolConfirmationEvent before executing destructive tools (rm, drop table), let the user approve/reject</li><li><strong>Multi-model routing</strong> — Use a fast/cheap model for simple tool calls, a powerful model for complex reasoning</li><li><strong>Web UI</strong> — The IAsyncEnumerable&lt;AgentEvent&gt; stream maps naturally to Server-Sent Events or SignalR</li><li><strong>MCP integration</strong> — Load tools dynamically from Model Context Protocol servers instead of hardcoding them</li><li><strong>Parallel tool execution</strong> — When the model requests multiple independent tool calls, execute them concurrently</li></ul><p>The agentic loop pattern is the same regardless. The model calls tools, you execute them, feed results back, repeat. Everything else is details.</p><h3>Wrapping Up</h3><p>Across these three articles, we’ve built a complete vibe coding tool:</p><ol><li><strong>Part 1</strong> — Connected to an LLM through the AI SDK’s unified ILanguageModel interface</li><li><strong>Part 2</strong> — Built tools that let the model read files, write files, edit code, search codebases, and run shell commands</li><li><strong>Part 3</strong> — Wrapped it all in an agentic loop that autonomously orchestrates tool calls until the task is complete</li></ol><p>The total application-specific code is about 50 lines (BlzAgent.cs). Everything else is reusable: the Agent, the event system, and the ToolRegistry work with any provider and any tool set.</p><p>That’s the power of building on a good abstraction layer. The AI SDK gives you the model interface. The Agent gives you the loop. You just bring the tools and the prompt.</p><p>Happy vibe coding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5991bf0b5c2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-3-building-the-agent-c5991bf0b5c2">Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 3: Building the Agent</a> was originally published in <a href="https://medium.com/predict">Predict</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 2: Building Tools]]></title>
            <link>https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-2-building-tools-fd78a9ff261d?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/fd78a9ff261d</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Thu, 12 Feb 2026 06:11:00 GMT</pubDate>
            <atom:updated>2026-02-13T01:49:15.409Z</atom:updated>
            <content:encoded><![CDATA[<ul><li>Part 1: <a href="https://medium.com/@deepakbattini/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-1-foundations-0c054f2c9485">The AI SDK — providers, models, messages, and generating text</a></li><li>Part 2 (this article): Building Tools — teaching the model to interact with the real world</li><li>Part 3: Building the Agent — the agentic loop that ties everything together</li></ul><h3>From Chatbot to Agent</h3><p>In Part 1, we built a chat loop. The model can answer questions, but it can’t <em>do</em> anything — it can’t read your files, create projects, or run builds. To make a vibe coding tool, the model needs to interact with the filesystem and shell.</p><p>This is what tool calling (also known as function calling) solves. You tell the model what tools are available, and it decides when and how to call them. The model doesn’t execute the tools itself — it returns structured “please call this tool with these arguments” messages, and your code runs them.</p><p>The flow looks like this:</p><pre>You: &quot;Create a hello.txt file&quot;<br>        │<br>        ▼<br>   ┌─────────┐<br>   │  Model   │ ──► ToolCall: write_file({ path: &quot;hello.txt&quot;, content: &quot;Hello!&quot; })<br>   └─────────┘<br>        │<br>        ▼<br>   Your code executes write_file, gets result: &quot;OK, wrote 6 chars&quot;<br>        │<br>        ▼<br>   Feed result back to model<br>        │<br>        ▼<br>   ┌─────────┐<br>   │  Model   │ ──► &quot;Done! I created hello.txt with a greeting.&quot;<br>   └─────────┘</pre><p>The AI SDK makes this easy with three building blocks: Tool definitions, ToolWithExecution, and ToolRegistry.</p><h3>How Tool Calling Works Under the Hood</h3><p>When you pass tools to the model, the SDK sends a JSON Schema describing each tool’s name, description, and parameters. The model can then respond with a special ToolCalls finish reason, indicating it wants to invoke one or more tools.</p><p>Here’s what the model sees (conceptually):</p><pre>{<br>  &quot;tools&quot;: [<br>    {<br>      &quot;name&quot;: &quot;write_file&quot;,<br>      &quot;description&quot;: &quot;Create or overwrite a file with the provided content.&quot;,<br>      &quot;parameters&quot;: {<br>        &quot;type&quot;: &quot;object&quot;,<br>        &quot;properties&quot;: {<br>          &quot;filePath&quot;: { &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;Absolute path to the file.&quot; },<br>          &quot;content&quot;: { &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;The content to write.&quot; }<br>        },<br>        &quot;required&quot;: [&quot;filePath&quot;, &quot;content&quot;]<br>      }<br>    }<br>  ]<br>}</pre><p>And here’s what comes back when the model decides to use the tool:</p><pre>result.FinishReason == FinishReason.ToolCalls<br>result.ToolCalls[0].ToolName == &quot;write_file&quot;<br>result.ToolCalls[0].Arguments == { &quot;filePath&quot;: &quot;hello.txt&quot;, &quot;content&quot;: &quot;Hello!&quot; }<br>result.ToolCalls[0].ToolCallId == &quot;call_abc123&quot;</pre><p>Your job: execute the tool call, and send the result back to the model as a new message.</p><h3>Building Your First Tool</h3><h3>Step 1: Define the Input Type</h3><p>Every tool needs a strongly-typed input. Use [JsonPropertyName] for the property names the model will use, and [Description] to tell the model what each parameter does:</p><pre>using System.ComponentModel;<br>using System.Text.Json.Serialization;<br>public class WriteFileInput<br>{<br>    [JsonPropertyName(&quot;filePath&quot;)]<br>    [Description(&quot;Absolute path to the file to create or overwrite.&quot;)]<br>    public string FilePath { get; set; } = &quot;&quot;;<br>    [JsonPropertyName(&quot;content&quot;)]<br>    [Description(&quot;The full content to write to the file.&quot;)]<br>    public string Content { get; set; } = &quot;&quot;;<br>}</pre><p>Why [JsonPropertyName] matters: The SDK&#39;s schema generator sends camelCase names to the model (so the model sees filePath), but C#&#39;s JsonSerializer.Deserialize defaults to PascalCase matching. Without [JsonPropertyName], the model&#39;s arguments won&#39;t deserialize correctly — all properties will be empty/default.</p><p>Why [Description] matters: These descriptions are included in the JSON Schema sent to the model. They&#39;re the model&#39;s documentation for how to use the tool. Good descriptions lead to fewer mistakes.</p><h3>Step 2: Create the Tool</h3><p>Use Tool.Create&lt;TInput, TOutput&gt;() to pair the definition with an execution function:</p><pre>using AiSdk.Tools;<br>var writeFileTool = Tool.Create&lt;WriteFileInput, string&gt;(<br>    &quot;write_file&quot;,<br>    &quot;Create a new file or overwrite an existing file with the provided content.&quot;,<br>    (input, ct) =&gt;<br>    {<br>        var dir = Path.GetDirectoryName(input.FilePath);<br>        if (!string.IsNullOrEmpty(dir) &amp;&amp; !Directory.Exists(dir))<br>            Directory.CreateDirectory(dir);<br>        File.WriteAllText(input.FilePath, input.Content);<br>        var lineCount = input.Content.Split(&#39;\n&#39;).Length;<br>        return Task.FromResult(<br>            $&quot;Successfully wrote {input.Content.Length} chars ({lineCount} lines) to {input.FilePath}&quot;);<br>    });</pre><p>Here’s what happens behind the scenes:</p><ol><li>Schema generation: Tool.Create calls JsonSchemaGenerator.GenerateSchema&lt;WriteFileInput&gt;(), which uses reflection to inspect the type — its properties, their types, [JsonPropertyName] attributes, [Description] attributes, and nullability. It produces a JSON Schema that describes the tool&#39;s parameters.</li><li>Definition creation: A ToolDefinition record is created with the name, description, and generated schema.</li><li>Execution pairing: The execution function is stored alongside the definition in a ToolWithExecution&lt;TInput, TOutput&gt; object.</li></ol><p>The result is a single object that knows both <em>how to describe itself to the model</em> and <em>how to execute when called</em>.</p><h3>How the Schema Generator Works</h3><p>The schema generator handles C# types recursively:</p><pre>| `string` | `{ &quot;type&quot;: &quot;string&quot; }` |<br>| `int`, `long` | `{ &quot;type&quot;: &quot;integer&quot; }` |<br>| `double`, `float` | `{ &quot;type&quot;: &quot;number&quot; }` |<br>| `bool` | `{ &quot;type&quot;: &quot;boolean&quot; }` |<br>| `enum` | `{ &quot;type&quot;: &quot;string&quot;, &quot;enum&quot;: [&quot;Value1&quot;, &quot;Value2&quot;] }` |<br>| `List&lt;T&gt;`, `T[]` | `{ &quot;type&quot;: &quot;array&quot;, &quot;items&quot;: { ... } }` |<br>| class/record | `{ &quot;type&quot;: &quot;object&quot;, &quot;properties&quot;: { ... }, &quot;required&quot;: [...] }` |</pre><p>Non-nullable properties are added to the required array. Nullable properties (string?, int?) are optional.</p><p>For example, this input type:</p><pre>public class GrepInput<br>{<br>    [JsonPropertyName(&quot;pattern&quot;)]<br>    [Description(&quot;Text or regex pattern to search for.&quot;)]<br>    public string Pattern { get; set; } = &quot;&quot;;<br>    [JsonPropertyName(&quot;path&quot;)]<br>    [Description(&quot;Directory to search in. Defaults to working directory.&quot;)]<br>    public string? Path { get; set; }<br>    [JsonPropertyName(&quot;include&quot;)]<br>    [Description(&quot;File filter (e.g. &#39;*.cs&#39;). Defaults to all files.&quot;)]<br>    public string? Include { get; set; }<br>}</pre><p>Generates this schema (sent to the model):</p><pre>{<br>  &quot;type&quot;: &quot;object&quot;,<br>  &quot;properties&quot;: {<br>    &quot;pattern&quot;: {<br>      &quot;type&quot;: &quot;string&quot;,<br>      &quot;description&quot;: &quot;Text or regex pattern to search for.&quot;<br>    },<br>    &quot;path&quot;: {<br>      &quot;type&quot;: &quot;string&quot;,<br>      &quot;description&quot;: &quot;Directory to search in. Defaults to working directory.&quot;<br>    },<br>    &quot;include&quot;: {<br>      &quot;type&quot;: &quot;string&quot;,<br>      &quot;description&quot;: &quot;File filter (e.g. &#39;*.cs&#39;). Defaults to all files.&quot;<br>    }<br>  },<br>  &quot;required&quot;: [&quot;pattern&quot;]<br>}</pre><p>Notice: pattern is required (non-nullable string), while path and include are optional (nullable string?).</p><h3>Step 3: Register Tools in a ToolRegistry</h3><p>When you have multiple tools, you need a registry to hold them all and dispatch execution by name:</p><pre>using AiSdk.Tools;<br><br>var registry = new ToolRegistry();<br>registry.Register(writeFileTool);<br>registry.Register(readFileTool);<br>registry.Register(bashTool);<br>// ... register more tools</pre><p>The registry provides two things:</p><p><strong>Definitions</strong> — the list of ToolDefinition objects to pass to the model:</p><pre>var options = new LanguageModelCallOptions <br>    {     <br>        Messages = history,     <br>        Tools = registry.Definitions  // ← All tool schemas for the model <br>    };</pre><p><strong>ExecuteAsync</strong> — type-erased execution by tool name:</p><pre>string result = await registry.ExecuteAsync(<br>    toolCall.ToolName,      // e.g. &quot;write_file&quot;<br>    toolCall.Arguments      // JsonDocument with the arguments<br>);</pre><p>The registry handles deserialization (JSON → your input type), execution, and error catching internally. If a tool throws, the registry catches the exception and returns an error string — this is important because you want the model to see the error and try to recover, not crash your application.</p><h3>Building a Real Tool Set</h3><p>For a vibe coding tool, you need tools that cover file operations, code search, and shell execution. Here’s how to build the essential ones.</p><h3>read_file — Read with Line Numbers</h3><pre>public class ReadFileInput<br>{<br>    [JsonPropertyName(&quot;filePath&quot;)]<br>    [Description(&quot;Absolute path to the file to read.&quot;)]<br>    public string FilePath { get; set; } = &quot;&quot;;<br>    [JsonPropertyName(&quot;offset&quot;)]<br>    [Description(&quot;Line offset to start from (0-based). Omit to read from the beginning.&quot;)]<br>    public int? Offset { get; set; }<br>    [JsonPropertyName(&quot;limit&quot;)]<br>    [Description(&quot;Max lines to read. Omit to read the entire file.&quot;)]<br>    public int? Limit { get; set; }<br>}<br><br>var readFileTool = Tool.Create&lt;ReadFileInput, string&gt;(<br>    &quot;read_file&quot;,<br>    &quot;Read file contents with line numbers. Supports offset and limit for large files.&quot;,<br>    (input, ct) =&gt;<br>    {<br>        if (!File.Exists(input.FilePath))<br>            return Task.FromResult($&quot;Error: File not found: {input.FilePath}&quot;);<br>        var lines = File.ReadAllLines(input.FilePath);<br>        int offset = Math.Max(0, input.Offset ?? 0);<br>        int limit = input.Limit ?? lines.Length;<br>        var sb = new StringBuilder();<br>        var selected = lines.Skip(offset).Take(limit).ToArray();<br>        for (int i = 0; i &lt; selected.Length; i++)<br>            sb.AppendLine($&quot;{offset + i + 1,5}| {selected[i]}&quot;);<br>        return Task.FromResult(sb.ToString());<br>    });</pre><p>Design note: Line numbers matter. When the model uses edit_file later, it needs to identify exact locations. The offset/limit parameters let it read portions of large files without blowing up the context.</p><h3>edit_file — Surgical Find-and-Replace</h3><pre>public class EditFileInput<br>{<br>    [JsonPropertyName(&quot;filePath&quot;)]<br>    [Description(&quot;Absolute path to the file to edit.&quot;)]<br>    public string FilePath { get; set; } = &quot;&quot;;<br><br>    [JsonPropertyName(&quot;oldString&quot;)]<br>    [Description(&quot;The exact string to find. Must match exactly including whitespace.&quot;)]<br>    public string OldString { get; set; } = &quot;&quot;;<br>    [JsonPropertyName(&quot;newString&quot;)]<br>    [Description(&quot;The replacement string.&quot;)]<br>    public string NewString { get; set; } = &quot;&quot;;<br>}<br><br>var editFileTool = Tool.Create&lt;EditFileInput, string&gt;(<br>&quot;edit_file&quot;,<br>&quot;Edit a file by finding and replacing an exact string. The old_string must appear exactly once.&quot;,<br>(input, ct) =&gt;<br>{<br>    if (!File.Exists(input.FilePath))<br>        return Task.FromResult($&quot;Error: File not found: {input.FilePath}&quot;);<br>    var content = File.ReadAllText(input.FilePath);<br>    if (!content.Contains(input.OldString))<br>        return Task.FromResult($&quot;Error: old_string not found in {input.FilePath}&quot;);<br>    // Ensure uniqueness - ambiguous edits are dangerous<br>    var count = CountOccurrences(content, input.OldString);<br>    if (count &gt; 1)<br>        return Task.FromResult(<br>            $&quot;Error: old_string found {count} times. Provide more context to make it unique.&quot;);<br>    var newContent = content.Replace(input.OldString, input.NewString);<br>    File.WriteAllText(input.FilePath, newContent);<br>    return Task.FromResult($&quot;Successfully edited {input.FilePath}&quot;);<br>});</pre><p>Design note: Requiring the oldString to be unique is critical. Without this, a naive replace could modify the wrong occurrence and silently corrupt the file. If the model gets an error, it can retry with more surrounding context to make the match unique.</p><h3>bash — Shell Execution</h3><p>This is the most powerful tool — and the trickiest to get right:</p><pre>public class BashInput<br>{<br>    [JsonPropertyName(&quot;command&quot;)]<br>    [Description(&quot;The shell command to execute.&quot;)]<br>    public string Command { get; set; } = &quot;&quot;;<br>[JsonPropertyName(&quot;workingDirectory&quot;)]<br>    [Description(&quot;Working directory. Defaults to project root.&quot;)]<br>    public string? WorkingDirectory { get; set; }<br>    [JsonPropertyName(&quot;timeout&quot;)]<br>    [Description(&quot;Timeout in seconds. Default is 60.&quot;)]<br>    public int Timeout { get; set; } = 60;<br>}<br><br>var bashTool = Tool.Create&lt;BashInput, string&gt;(<br>    &quot;bash&quot;,<br>    &quot;Execute a shell command. Returns stdout, stderr, and exit code.&quot;,<br>    async (input, ct) =&gt;<br>    {<br>        var psi = new ProcessStartInfo<br>        {<br>            FileName = &quot;cmd.exe&quot;,<br>            Arguments = $&quot;/c {input.Command}&quot;,<br>            WorkingDirectory = input.WorkingDirectory ?? workingDir,<br>            RedirectStandardOutput = true,<br>            RedirectStandardError = true,<br>            RedirectStandardInput = true,<br>            UseShellExecute = false,<br>            CreateNoWindow = true<br>        };<br>        // Skip interactive prompts in CI-style tools<br>        psi.Environment[&quot;CI&quot;] = &quot;true&quot;;<br>        psi.Environment[&quot;npm_config_yes&quot;] = &quot;true&quot;;<br>        var process = Process.Start(psi)!;<br>        process.StandardInput.Close(); // EOF prevents hanging on prompts<br>        // ... read output, handle timeouts, return result<br>    });</pre><p>Two critical gotchas for bash tools:</p><ol><li>Confirmation prompts: Commands like npm create vite@latest ask &quot;Ok to proceed? (y)&quot; and block forever. Fix: set CI=true and npm_config_yes=true environment variables, redirect stdin and close it immediately.</li><li>Long-running processes: npm run dev starts a dev server that <em>never exits</em>. If you use ReadToEndAsync + WaitForExitAsync, you block forever. Fix: read output incrementally and use an idle timeout — if the process stops producing output for 5 seconds (e.g., after printing &quot;ready in 500ms&quot;), return what you have and let the process continue in the background.</li></ol><h3>Organizing Tools in a Factory</h3><p>Group all tool creation in a static factory class:</p><pre>public static class VibeCodingTools<br>{<br>    public static ToolRegistry CreateRegistry(string workingDirectory)<br>    {<br>        var registry = new ToolRegistry();<br>        registry.Register(CreateReadFileTool());<br>        registry.Register(CreateWriteFileTool());<br>        registry.Register(CreateEditFileTool());<br>        registry.Register(CreateGlobTool(workingDirectory));<br>        registry.Register(CreateGrepTool(workingDirectory));<br>        registry.Register(CreateBashTool(workingDirectory));<br>        registry.Register(CreateMkdirTool());<br>        // ... more tools<br>        return registry;<br>    }<br>    private static ToolWithExecution&lt;ReadFileInput, string&gt; CreateReadFileTool() =&gt;<br>        Tool.Create&lt;ReadFileInput, string&gt;(&quot;read_file&quot;, &quot;...&quot;, (input, ct) =&gt; { ... });<br>    // ... other Create methods<br>}</pre><p>This keeps tool definitions clean and testable. The workingDirectory parameter is threaded through to tools that need a default base path (glob, grep, bash).</p><h3>Tool Calling in Action</h3><p>Here’s the manual version of what the agent loop does (we’ll automate this in Part 3):</p><pre>var registry = VibeCodingTools.CreateRegistry(@&quot;C:\projects&quot;);<br>var history = new List&lt;Message&gt;<br>{<br>    new(MessageRole.System, &quot;You are a coding assistant. Use your tools.&quot;),<br>    new(MessageRole.User, &quot;Create a file called hello.txt with &#39;Hello, World!&#39;&quot;)<br>};<br>// 1. Call the model with tools available<br>var result = await model.GenerateAsync(new LanguageModelCallOptions<br>{<br>    Messages = history,<br>    Tools = registry.Definitions<br>});<br>// 2. Check if the model wants to call tools<br>if (result.FinishReason == FinishReason.ToolCalls)<br>{<br>    foreach (var toolCall in result.ToolCalls!)<br>    {<br>        Console.WriteLine($&quot;Tool: {toolCall.ToolName}&quot;);<br>        // 3. Execute the tool<br>        var toolResult = await registry.ExecuteAsync(<br>            toolCall.ToolName, toolCall.Arguments);<br>        Console.WriteLine($&quot;Result: {toolResult}&quot;);<br>        // 4. Feed the result back to the model<br>        history.Add(new Message(MessageRole.User,<br>            $&quot;&lt;tool_result name=\&quot;{toolCall.ToolName}\&quot;&gt;{toolResult}&lt;/tool_result&gt;&quot;));<br>    }<br>    // 5. Call the model again so it can respond or call more tools<br>    result = await model.GenerateAsync(new LanguageModelCallOptions<br>    {<br>        Messages = history,<br>        Tools = registry.Definitions<br>    });<br>    Console.WriteLine(result.Text);<br>}</pre><p>The model might call one tool, or five tools, or call tools in a chain where later calls depend on earlier results. That’s why we need a loop — which is exactly what Part 3 covers.</p><h3>The Tool Design Checklist</h3><p>When building tools for an AI agent, keep these principles in mind:</p><ol><li>Return errors, don’t throw. The model should see “Error: File not found” and try something else, not crash your application. The ToolRegistry wraps execution in try-catch, but returning clean error strings gives the model better information.</li><li>Descriptions are documentation. The model reads your tool descriptions and parameter descriptions to decide when and how to use each tool. Be specific. “Execute a shell command” is better than “Run stuff.”</li><li>Validate inputs defensively. The model might send malformed paths or missing arguments. Check for nulls, verify paths exist, validate ranges.</li><li>Truncate large outputs. Tool results go back into the conversation history and consume tokens. If grep finds 10,000 matches, truncate to 100 with a note. If a file is 50KB, show the first portion.</li><li>Make tools composable. The model should be able to read_file → edit_file → bash (run tests) in sequence. Each tool should work independently.</li></ol><h3>What’s Next</h3><p>We now have a model and a set of tools. But the manual “call model → check for tools → execute → feed back → repeat” loop is tedious and limited. What if the model needs to call tools 10 times in a row?</p><p>In Part 3, we’ll build the Agent — a generic agentic loop that:</p><ul><li>Calls the model with conversation history and tools</li><li>Automatically executes any tool calls</li><li>Feeds results back and loops until the model produces a final text response</li><li>Handles conversation summarization when context gets too long</li><li>Emits typed events so your UI can display progress in real time</li></ul><p>This is where everything comes together into a real vibe coding tool.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fd78a9ff261d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-2-building-tools-fd78a9ff261d">Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 2: Building Tools</a> was originally published in <a href="https://medium.com/predict">Predict</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 1: Foundations]]></title>
            <link>https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-1-foundations-0c054f2c9485?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/0c054f2c9485</guid>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Wed, 11 Feb 2026 06:53:14 GMT</pubDate>
            <atom:updated>2026-02-12T02:52:23.506Z</atom:updated>
            <content:encoded><![CDATA[<blockquote><em>This is Part 1 of a 3-part series. By the end, you’ll have built a fully functional AI coding agent — a CLI tool that can create files, run builds, search code, and execute shell commands, all driven by an LLM.</em></blockquote><ul><li><strong>Part 1</strong> (this article): The AI SDK — providers, models, messages, and generating text</li><li><strong>Part 2</strong>: Building Tools — teaching the model to interact with the real world</li><li><strong>Part 3</strong>: Building the Agent — the agentic loop that ties everything together</li></ul><h3>What We’re Building</h3><p>“Vibe coding” is a term coined by Andrej Karpathy — the idea that you describe what you want in natural language and an AI builds it. Tools like Cursor, Windsurf, and Claude Code do this inside editors. We’re going to build one from scratch as a standalone CLI, using the <strong>AI SDK for .NET</strong> NuGet package.</p><p>Here’s what the finished product looks like:</p><pre>You &gt; Create a React todo app with add, complete, and delete features</pre><pre>  &gt; mkdir  C:\projects\todo-react<br>  &gt; bash   npm create vite@latest todo-react -- --template react<br>    OK [exit code: 0]<br>  &gt; write_file  C:\projects\todo-react\src\App.jsx<br>    OK wrote 1371 chars<br>  &gt; bash   cd C:\projects\todo-react &amp;&amp; npm install &amp;&amp; npm run build<br>    OK [exit code: 0]<br>.........</pre><pre>Done! I created a React todo app at C:\projects\todo-react with...</pre><p>The model decides what tools to call, in what order, and handles errors autonomously. Our job is to give it the right tools and a loop to run in.</p><p>Let’s start with the foundation: the AI SDK itself.</p><h3>Getting Started</h3><p>Create a new console app and add the AI SDK:</p><pre>dotnet new console -n VibeCoder<br>cd VibeCoder<br>dotnet add package AiSdk</pre><p>That single package gives you access to 30+ providers — OpenAI, Anthropic, Azure OpenAI, Google, Groq, Mistral, and many more — through a unified interface.</p><h3>Core Concepts</h3><p>The AI SDK is built around a few key abstractions. Once you understand these, everything else falls into place.</p><h3>1. The Provider — Creating a Model</h3><p>Every provider has a static factory class. You call it to get a model instance:</p><pre>using AiSdk.Providers.Azure;<br>var model = AzureOpenAIProvider.CreateChatModel(<br>    deploymentName: &quot;gpt-4o&quot;,<br>    endpoint: &quot;https://my-resource.openai.azure.com&quot;,<br>    apiKey: &quot;your-api-key&quot;<br>);</pre><p>Want to switch to OpenAI directly?</p><pre>using AiSdk.Providers.OpenAI;<br>var model = OpenAIProvider.CreateChatModel(<br>    modelId: &quot;gpt-4o&quot;,<br>    apiKey: &quot;sk-...&quot;<br>);</pre><p>Or Anthropic?</p><pre>using AiSdk.Providers.Anthropic;<br>var model = AnthropicProvider.CreateChatModel(<br>    modelId: &quot;claude-3-5-sonnet-20241022&quot;,<br>    apiKey: &quot;sk-ant-...&quot;<br>);</pre><p>The pattern is always the same: a static CreateChatModel method that returns an ILanguageModel. Some providers also have convenience methods like OpenAIProvider.GPT4(apiKey) for common models.</p><p><strong>The key insight:</strong> every provider returns the same ILanguageModel interface. Your application code never needs to know which provider is behind it. This is what makes the SDK powerful — you can swap providers without changing your logic.</p><h3>2. Messages — The Conversation</h3><p>LLMs work with a conversation history — a list of messages with roles:</p><pre>using AiSdk.Abstractions;<br>var messages = new List&lt;Message&gt;<br>{<br>    new(MessageRole.System, &quot;You are a helpful coding assistant.&quot;),<br>    new(MessageRole.User, &quot;What is a record in C#?&quot;)<br>};</pre><p>The four roles:</p><p>SystemSets behavior, context, and rules</p><p>UserInput from the human (or tool results fed back)</p><p>AssistantModel&#39;s responses</p><p>ToolResults from tool/function execution</p><p>A Message is a simple record:</p><pre>public record Message(<br>    MessageRole Role,<br>    string Content,<br>    string? Name = null,<br>    IReadOnlyDictionary&lt;string, object&gt;? Metadata = null);</pre><h3>3. Generating Text — Your First API Call</h3><p>To call the model, create a LanguageModelCallOptions and call GenerateAsync:</p><pre>var options = new LanguageModelCallOptions<br>{<br>    Messages = messages,<br>    MaxTokens = 500,<br>    Temperature = 0.7<br>};<br><br>var result = await model.GenerateAsync(options);<br>Console.WriteLine(result.Text);<br>Console.WriteLine($&quot;Tokens used: {result.Usage.TotalTokens}&quot;);<br>Console.WriteLine($&quot;Finish reason: {result.FinishReason}&quot;);</pre><p>The result gives you:</p><ul><li><strong>Text</strong> — the generated content</li><li><strong>FinishReason</strong> — why the model stopped (Stop, Length, ToolCalls, etc.)</li><li><strong>Usage</strong> — token counts (InputTokens, OutputTokens, TotalTokens)</li><li><strong>ToolCalls</strong> — any tool calls the model wants to make (we&#39;ll use this in Part 2)</li></ul><h3>4. The Convenience Layer — AiClient</h3><p>For simple use cases, the SDK provides AiClient as a higher-level API:</p><pre>using AiSdk;<br>// Simple text generation<br>var result = await AiClient.GenerateTextAsync(model, new GenerateTextOptions<br>{<br>    System = &quot;You are a helpful assistant.&quot;,<br>    Prompt = &quot;Explain dependency injection in one paragraph.&quot;<br>});<br><br>Console.WriteLine(result.Text);</pre><p>AiClient handles building the message array from System + Prompt for you. It also supports streaming:</p><pre>await foreach (var chunk in AiClient.StreamTextAsync(model, new GenerateTextOptions<br>{<br>    Prompt = &quot;Write a haiku about C#&quot;<br>}))<br>{<br>    Console.Write(chunk.Text);<br>}</pre><h3>5. Structured Output — Getting Objects Back</h3><p>One of the most powerful features: you can ask the model to return typed C# objects instead of raw text.</p><pre>public record MovieReview<br>{<br>    [Description(&quot;Rating from 1-10&quot;)]<br>    public int Rating { get; init; }<br>    public string Summary { get; init; } = &quot;&quot;;<br>    [Description(&quot;Key themes identified&quot;)]<br>    public List&lt;string&gt; Themes { get; init; } = new();<br>}<br><br>var review = await AiClient.GenerateObjectAsync&lt;MovieReview&gt;(model, new GenerateObjectOptions<br>{<br>    Prompt = &quot;Review the movie Inception&quot;,<br>    Mode = &quot;tool&quot;  // Uses tool calling for structured output<br>});<br><br>Console.WriteLine($&quot;Rating: {review.Object.Rating}/10&quot;);<br>Console.WriteLine($&quot;Summary: {review.Object.Summary}&quot;);</pre><p>The SDK automatically generates a JSON Schema from your C# type (using [Description] attributes and [JsonPropertyName] for naming), sends it to the model, and deserializes the response back into your type.</p><p>Two modes are supported:</p><ul><li><strong>&quot;tool&quot;</strong> — Creates a hidden tool definition; the model &quot;calls&quot; it with the structured data</li><li><strong>&quot;json&quot;</strong> — Appends the schema to the system prompt and parses the JSON response</li></ul><h3>Understanding LanguageModelCallOptions</h3><p>This is the main options record you’ll work with when calling models directly:</p><pre>public record LanguageModelCallOptions<br>{<br>    // Required<br>    public required IReadOnlyList&lt;Message&gt; Messages { get; init; }<br>   // Tools (Part 2)<br>    public IReadOnlyList&lt;ToolDefinition&gt;? Tools { get; init; }<br>    public string? ToolChoice { get; init; }  // &quot;auto&quot;, &quot;none&quot;, &quot;required&quot;<br>    // Generation parameters<br>    public int? MaxTokens { get; init; }<br>    public double? Temperature { get; init; }    // 0.0 = deterministic, 2.0 = creative<br>    public double? TopP { get; init; }<br>    public int? TopK { get; init; }<br>    public double? PresencePenalty { get; init; }<br>    public double? FrequencyPenalty { get; init; }<br>    public IReadOnlyList&lt;string&gt;? StopSequences { get; init; }<br>    public int? Seed { get; init; }              // For reproducible outputs<br>}</pre><p>For our vibe coding tool, we’ll mostly care about Messages and Tools. The generation parameters can be left at defaults for most coding tasks (models tend to work well at low temperature for code).</p><h3>Putting It Together — A Minimal Chat Loop</h3><p>Here’s a working chat application in ~30 lines:</p><pre>using AiSdk.Abstractions;<br>using AiSdk.Providers.OpenAI;<br>var model = OpenAIProvider.CreateChatModel(&quot;gpt-4o&quot;, apiKey: &quot;sk-...&quot;);<br>var history = new List&lt;Message&gt;<br>{<br>    new(MessageRole.System, &quot;You are a helpful coding assistant.&quot;)<br>};<br>while (true)<br>{<br>    Console.Write(&quot;You &gt; &quot;);<br>    var input = Console.ReadLine();<br>    if (string.IsNullOrWhiteSpace(input)) continue;<br>    if (input == &quot;/quit&quot;) break;<br>    history.Add(new Message(MessageRole.User, input));<br>    var result = await model.GenerateAsync(new LanguageModelCallOptions<br>    {<br>        Messages = history<br>    });<br>    history.Add(new Message(MessageRole.Assistant, result.Text ?? &quot;&quot;));<br>    Console.WriteLine($&quot;\nAssistant &gt; {result.Text}\n&quot;);<br>}</pre><p>This maintains conversation history across turns, so the model remembers context. But it can only talk — it can’t <em>do</em> anything. It can’t create files, run commands, or interact with your filesystem.</p><p>That’s what tools are for.</p><h3>What’s Next</h3><p>In <strong>Part 2</strong>, we’ll teach the model to interact with the real world by building tools. You’ll learn:</p><ul><li>How the SDK’s tool system works (Tool.Create, ToolWithExecution, ToolRegistry)</li><li>How C# types automatically become JSON Schemas for the model</li><li>How to build real tools: read_file, write_file, edit_file, bash, and more</li><li>How tool calling works end-to-end: model requests a tool → you execute it → feed the result back</li></ul><p>The tool system is where “chatbot” becomes “agent.”</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0c054f2c9485" width="1" height="1" alt=""><hr><p><a href="https://medium.com/predict/build-your-own-vibe-coding-tool-with-ai-sdk-for-net-part-1-foundations-0c054f2c9485">Build Your Own Vibe Coding Tool with AI SDK for .NET — Part 1: Foundations</a> was originally published in <a href="https://medium.com/predict">Predict</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Many world interpretations for building a powerful computer — Is wave the reality?]]></title>
            <link>https://medium.com/analytics-vidhya/many-world-interpretations-for-building-a-powerful-computer-is-wave-the-reality-96503881f33f?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/96503881f33f</guid>
            <category><![CDATA[quantum-computer]]></category>
            <category><![CDATA[quantum-computing]]></category>
            <category><![CDATA[quantum-physics]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Sat, 13 Aug 2022 03:05:03 GMT</pubDate>
            <atom:updated>2022-08-13T11:20:58.431Z</atom:updated>
            <content:encoded><![CDATA[<h3>Many world interpretations for building a powerful computer — What are we: Particle or Wave?</h3><p>In my <a href="https://medium.com/analytics-vidhya/many-world-interpretation-towards-building-a-powerful-computer-35c517042360">previous blog</a>, we talked about some of the basic theoretical requirements to build a quantum computer. I would like to start introducing the mathematics behind its design in the upcoming blogs. I understand for this we need some background in quantum mechanics, so I will try to explain some of the concepts in a simplified manner.</p><p>In the last blog “the interference section”, I mentioned about the fundamental structure of the universe is like a wave-like form which is probably hard to imagine and with that reference, I gave an example of electromagnetic radio waves carrying information and us being a receiver who decodes it to create the reality in physical form. I would like to expand more on that statement and discuss in detail an experiment that can prove that statement.</p><p>An idea was conceived by a genius mind Thomas Young in 1803 which can prove the notion that we are made of either particles or wave-like or both, but due to a lack of experimental confirmation from the victorian era scientists, it was forgotten. It lay dormant for two centuries until Wheeler and Thibodeaux proposed an experiment that re-produced Young’s original idea with success. We can go through the experiment again below and understand the concept of why reality is different than we think.</p><h3>Understanding Bullets and Waves Behaviour</h3><p>Imagine that you have a wall with two narrow slits and a sandbox after it. A machine gun is set up right in front of the wall and since we have a machine gun and not something else, you might expect that we are going to shoot in the direction of this wall having two slits.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fxesgl8gzoEFjXju-gm5EA.png" /></figure><p>The gun is fired multiple rounds and we can see the bullets pass through the slits which will have equal chances to pass through. Those bullets which pass through the slits are going to reach the yellow sandbox and get stuck there.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A96R47CX9_iVcWI2eiAP2g.png" /></figure><p>After the experiment, we can retrieve the bullets from the sandbox and count them. When counting the bullets, we can draw a graph. The x-axis here corresponds to the position of the bullet in the box, it’s how far it went from the line of symmetry of the whole set. The y-axis will correspond to the number of bullets found in this position.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/957/1*aTLbWQzRMgHbNsaRtD7c5Q.png" /></figure><p>If we repeat the experiment with a single slit at a time, we see predictable behaviour which is pretty straightforward to understand</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ooradIpdXH5euGYWXPvRtw.png" /></figure><p>Now let&#39;s use something completely different, the screen with two slips is now going to be placed in the water. Instead of a machine gun, we are going to have some source of water waves and an oscillating bobber. which will oscillate with some frequency and produce waves. These waves will pass through the slits and will reach the detector.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*ZXxdagD970MN2ZoT_iy42Q.png" /></figure><p>To detect those final waves, we are going to place many smaller bobbers along the line parallel to the screen at some distance. These bobbers will swing due to the secondary waves and produce some work for us to measure. We probably remember from school that waves don’t transmit matter, but they do transmit energy.</p><p>We will start the experiment with only one slit open at a time and see the result which is again predictable.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QxieBxaqaBXhItNFoLqJcw.png" /></figure><p>The graph above shows the power produced by each bobber. The bobbers which are closer to the slit, produce more power, while those far away slit. It is absolutely normal since the energy of the wave is distributed along the whole wavefront. The power which we are measuring is also called the intensity of the wave. From physics, we know that the intensity of the wave is proportional to its squared amplitude.</p><p>Now, when we have the graphs of intensities with the left and the right slits being opened separately, can we predict the resulting graph for the two slits opened simultaneously? Below is the experiment result, when the waves pass through the slit and it collides with each after passing the slit forming another set of waves or cancelling each other. In the end, the intensity (power) of the wave is found all over the detector.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/1*DNtM3PHkte9kZZdvNYVSjA.png" /></figure><p>So that means the resulting graph of the wave intensity with two slits open is not equal to the sum of the graphs with the left and the right slits opened separately which is the case with the bullet are equal.</p><h3><strong>Understanding Fundamental Particle Behaviour</strong></h3><p>We have just seen with the above experiment gives us quite different results for bullets and waves. When we perform it with the particles, like bullets, the resulting graph with both slits opened is just the sum of the graphs with each slit opened separately. When they perform this experiment with the waves, there are no particles to count. Instead of the particles, we measure the characteristic of the wave called intensity. The resulting graph for this intensity with both slits opened is not at all the sum of the intensities with the slits opened separately.</p><p>We will now make use of the quantum particles like photons and electrons which are fundamental building blocks for an atom. We will continue with the setup, as we had with the bullets, but instead of a machine gun, we now have the source of photons, which can fire photons one by one. We have a special detector behind the slit which will detect the photons and we can count the hits by counting the number of spots formed on the detector.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*gWDLvWGmT3uqiigNjd3OWA.png" /></figure><p>At the start of the experiment, we will just fire the photon&#39;s particle and see the result in the detector at the end. This means that we are not observing the process of how the photons pass the slits and reach the detector. At the end of the experiment, we see a result something like we have observed in the above wave experiment using water.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*U9JxenlRjdirLFmUyEC5Kg.png" /></figure><p>This is strange, because we belive the photons are something like a bullet. In order to see why it behaves like waves, we have now placed a camera like an observer in front of the slit which will record the entire process to see how the photons are passed through the detector. We rerun the experiment and see the result at the end along with the recording. And the thing which is observed is pure bullet like behaviour which depicts the photons are like particles. There is no wave like character.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*_wTjMY52OD9u9-_wtMRWWw.png" /></figure><p>Repeating the experiment with electrons with and without a camera (an observer), we see these two different results.</p><p>What’s going on here? It’s as though the electrons or photons “know” whether you’re watching them or not. The very act of observing this setup — of asking “which slit did each electron pass through?” — changes the outcome of the experiment. If you measure which slit the quantum passes through, it behaves as though it passes through one and only one slit: it acts like a classical particle (like a bullet). If you don’t measure which slit the quantum passes through, it behaves as a wave, acting like it passed through both slits simultaneously and producing an interference pattern.</p><h3>Are we at one place or everywhere?</h3><p>Since we know we are made up of these fundamental particles, that means as a complex being we are unable to experience this wave nature which technically means being everywhere. We are always in a constant state of observation through various senses and that makes us solid physical beings and observe one event or moment at any point in time.</p><p>At this point, the whole problem gets very difficult to get your mind around. But don’t get too worried about this. As <a href="http://en.wikiquote.org/wiki/Quantum_mechanics">Richard Feynman</a>, Nobel Laureate and the truly brilliant man said: <em>“I think I can safely say that nobody understands quantum mechanics.”</em> Most people working in this field just get used to the concept and get on with their lives, or become philosophers.</p><p>And as for reality?</p><p>I think Professor Feynman has the <a href="http://en.wikiquote.org/wiki/Richard_Feynman">last word</a> on that one, too: “ <em>… the paradox is only a conflict between reality and your feeling of what reality ought to be</em>.”</p><p>In the next few blogs, we will start going into more technical, look into some mathematics, learn how we can start building algorithms in the quantum computer and might as well do programming. That also means we will start running our code in the 5th dimension and use the true power of parallel computing.</p><p>See you in the next blogs ….</p><p>Also published in my tech quantum blog: <a href="https://www.tech-quantum.com/many-world-interpretations-for-building-a-powerful-computer-is-wave-the-reality/">https://www.tech-quantum.com/many-world-interpretations-for-building-a-powerful-computer-is-wave-the-reality/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=96503881f33f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/many-world-interpretations-for-building-a-powerful-computer-is-wave-the-reality-96503881f33f">Many world interpretations for building a powerful computer — Is wave the reality?</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Many world interpretation towards building a powerful computer]]></title>
            <link>https://medium.com/analytics-vidhya/many-world-interpretation-towards-building-a-powerful-computer-35c517042360?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/35c517042360</guid>
            <category><![CDATA[next-generation]]></category>
            <category><![CDATA[supercomputer]]></category>
            <category><![CDATA[quantum-computing]]></category>
            <category><![CDATA[parallel-computing]]></category>
            <category><![CDATA[quantum-physics]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Sun, 05 Sep 2021 12:59:51 GMT</pubDate>
            <atom:updated>2022-01-08T03:36:17.635Z</atom:updated>
            <content:encoded><![CDATA[<p>Today’s blog is about a next-generation computer defined to be very powerful and capable to solve complex problems (like breaking cipher) in a matter of secs which the current supercomputers are not able to do. I am not sure how true this is that but let’s see by understanding and realising it.</p><p>In this post, we will concentrate more on the physical nature of that computer and understand what does quantum physics have to do with it which will be the source of the unlimited computing power. Quantum physics is itself very mysterious and we have only known about the weird behaviour on the subatomic level like electrons and photons.</p><h3>An example</h3><p>Let’s take an example of a problem where a person standing in a junction, has to decide on one path to reach his destination, only one path is correct and the rest 3 are dead-end.</p><p>In a classical computer, we would solve by going through each path, come back to start if found a dead end and then take another path, which in this case would take a maximum of 4 shots to find the correct route. But with a quantum computer, it will take only one shot to find the correct path. Even though we complicate the problem by making thousands of paths through that junction, we still can find the correct path in just one shot and of course, it&#39;s not limited to that number.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/565/0*RUtlia9U_OpbPrZ8.png" /></figure><p>To explain better how it works I will have to take through these three basic principles of quantum physics which are the minimum theoretical requirements to build a quantum computer:</p><h3>Continuum of states</h3><p>A state can be defined as a specific property of any physical object/entity in space and time. A switch can be in one of the 2 states: On or off. Flipping a coin gives you one of the two states: Head or Tail.</p><p>In the above example of the person in the 4-path junction, when he moves through the space and time his state will change from 0 -&gt; 1 or 1 -&gt; 0 -&gt; 2 or 2 -&gt; 0 -&gt; 3 and so on. This is often a general phenomenon of classical physics, whereas in a quantum world a switch can be in both the states On and Off, flipping of coin will result in both Head and Tail, and the person trying to find the correct path will be everywhere.</p><p>This term is more often refer to as “<strong>Superposition</strong>”.</p><p>In a classical computer, such states are defined in a bit (0 or 1). So, one bit can hold one of the 2 states, 2 bits can hold one of the 4 states (00, 01, 10, 11). In the case of a quantum computer, Qubit (Quantum Bit) is used where 1 qubit can hold both 2 states (0 and 1) at the same time and 2 qubits can hold all 4 states at the same time.</p><p>Pretty weird phenomenon right, which means I can be at my work and home and driving at the same time, but then in reality why can’t I experience all of them at the same time and only be available at work or home or driving? If I flip a coin, why don’t I see head and tail at the same time? I guess it’s our limitation as physical beings where we can see one thing or event at any time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/0*6Pd3A9FcQug9ZYuU.png" /></figure><h3>Randomness</h3><p>With the above question in mind, let&#39;s try to see what is the true meaning of randomness.</p><p>In the event of flipping a coin, you throw it and saw the value, its heads in your case. This is the value you see which looks to be random but it is not truly random. If you want to predict flipping a coin brings a head or tail, you can try to measure all the initial parameters like the position of the coin itself, your body, air at the room, etc with sufficient accuracy. But in actuality, we really don’t know what causes the result to be a head or tail and looks truly random.</p><p>Does that mean randomness is some lack of information? Something seems to us random, but we believe that if we just had more information, then we could certainly predict an outcome. It is really hard to imagine the real randomness when the outcome cannot be predicted with all information available.</p><p>Now imagine in the example of the person is you and in search of the correct path, and we have four identical universes where this event takes place. In the first one, you moved from point 0 to 1 takes the upper way, and hit the dead end. While in the second universe, you took the lower way to point 3), and hit the dead end and so on for the rest two-path as well. Now, the most important part since these universes are completely identical at the start of the experiment, there are four identical you observing the result there. Does that mean you truly choose a random way whereas in actual you took all the four paths but happened in different universes?</p><p><strong>There’s no randomness at all</strong>, but for you, subjectively, the result appears to be random. Because you cannot be in all places simultaneously. You observe the random result, but different for different you. I am not trying to convince you to accept this picture of different universes literally. But mathematically, the behaviour of the electron in its own realm works like that. In quantum mechanics, there’s no such thing as a trajectory of an electron or a photon or any other small particle. We can detect and fix the points of the electron departure and arrival here, but we can say almost nothing about what happens in between.</p><p>This true meaning of randomness gives the immense potential for parallel computing power. It&#39;s just about throwing a problem in the air and we know now there are multiple possible outcomes that we just need to know how to interpret giving us all the possible results in one shot.</p><h3>Interference</h3><p>If we accept that these different possibilities of an event can be implemented somewhere in a computer, the next natural question is, how we can see all the results?</p><p>“A German philosopher Immanuel Kant stated that the concept of the space is imminent to our brain, not to the real world itself, and the real world itself is maybe something very different.”</p><p>“Albert Einstein once wrote: People like us who believe in physics know that the distinction between past, present and future is <strong>only a stubbornly persistent illusion</strong>. Time, in other words, he said, is an illusion. Many physicists since have shared this view, that true reality is timeless”</p><p>“An American physicist, Hugh Everett III in 1957 proposed this new concept of a multiverse, probably an infinite stack of universes, which are in some sense parallel.”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/397/0*a8bD42ZTOi8G3Vtt.png" /><figcaption>State of all 4 universes at time t0</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/373/0*-W51eqvo7aduoKa-.png" /><figcaption>State of all 4 universes after time t1</figcaption></figure><p>We can imagine at the beginning of time all these universes were identical. But with the passing of time, random events occur, which divide these universes into different types depending on the results of these random events. When we observe some random event our previously identical copies in different universes start to differ and these different copies from now on can act differently. We cannot interact with each other since we are in different universes. So, there is so much available computing power in this multiverse, we are not able to use it since there’s no way we could collect the result of this distributed computation, right? Well, fortunately, sometimes we can move it, and this can be done through the process of interference.</p><p>Interference is not an act of measurement, because measurement collapses the possibilities to one reality. In simple terms when you flip the coin and hold it closed in your palm, that state is called super-position where you have the power to imagine both the universe with different results. The act of opening the palm and seeing the result collapse the possible outcome to one state. There is a scientific term to it called “Wave function collapse”.</p><p>That means the quantum computer will not try to see the result rather it will use interference to collect all the results from different universes. What is interference and how can we imagine that? A good example of interference can be seen in the below image, where when two waves collide with each other it creates an additional set of waves with different amplitudes. If the two waves have the same frequency then the collision results in constructive interference and if they are different they result in destructive interference. At any point, the interference gives us an idea to calculate the state of the two waves before the collision.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*dnFA_F8hVX1CudXn.jpg" /></figure><p>Now, what do the waves have to do with us? Well, if we see the structure of the physical universe, they are made up of atoms. Further dividing atoms give subatomic particles like electrons, photons etc and at some point further dividing the particles it&#39;s believed that we are made up of some sort of electromagnetic waves. These waves carry information that basically constructs the physical universe. This could be imagined similar to the radio waves surrounding us which carries information of TV, FM, news, mobile comms etc but the device is something that tunes with that radiofrequency and decodes the information to something meaningful like visuals or songs.</p><p>If you imagine all these infinite parallel universes at the same place around us and are vibrating at different frequencies, then the interference between these electromagnetic waves we can extract something for our distributed computation. Running different paths of computation in different universes and make them interfere, then we will be able to collect some information about the result from all these branches. This is what quantum computing is all about. Sounds simple, can we implement it?</p><p>Theoretically yes, but practically we have a problem which I think you also have imagined that. Let&#39;s say we are flipping the coin and have universe A and B where we will get to see different results. Both the universe where the event happens should be equal means A — B = 0. When the flip coin event happens and performing interference to collect results we should be able to get the result of only that flip event. But in reality, the universe is really very very big and billions of random events are happening every second and the waves of those random events can interfere with the coin flip event adding errors to the collected results. To have the desired result there are few things which are been done to reduce the errors:</p><ul><li>Make the computation very fast to eliminate the probability of another random event in the environment.</li><li>Reduce the temperature of the surrounding environment which slows down the random event and gives time while reading interference. That&#39;s why you will see the quantum computers kept at -200 degrees Celcius.</li><li>Try to isolate the computing system as much as possible which could be the hardest thing to do.</li></ul><p>I guess research is in progress to find the best and effective approach to collect the result from the multiverse. I know it&#39;s a long way to go, but at least with this post, I wanted to give some basic understanding which probably tries to open our minds to think in a very different way. Just closing my thought with this quote from Mark Helprin, Winter Tales “If nothing is random, and everything is predetermined, how can there be free will? The answer to that is simple. Nothing is predetermined; it is determined, or was determined, or will be determined.”</p><p><em>Originally published at </em><a href="https://www.tech-quantum.com/many-world-interpretation-towards-building-a-powerful-computer"><em>https://www.tech-quantum.com</em></a><em> on September 5, 2021.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=35c517042360" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/many-world-interpretation-towards-building-a-powerful-computer-35c517042360">Many world interpretation towards building a powerful computer</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vue Single Page Application with ASP.NET Core — No Node Js]]></title>
            <link>https://deepakbattini.medium.com/vue-single-page-application-with-asp-net-core-no-node-js-22b9a79309dc?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/22b9a79309dc</guid>
            <category><![CDATA[vuejs]]></category>
            <category><![CDATA[aspnetcore]]></category>
            <category><![CDATA[single-page-applications]]></category>
            <category><![CDATA[aspnet-mvc]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Sun, 29 Aug 2021 07:11:43 GMT</pubDate>
            <atom:updated>2021-08-29T07:13:16.223Z</atom:updated>
            <content:encoded><![CDATA[<h3>Vue Single Page Application with ASP.NET Core — No Node Js</h3><p>In this post, we will explore how to build single page application using Vue JS and ASP.Net core. I promise there won’t be any Node JS installation and running npm scripts to make your project folder bulky.</p><p>First of all, download and install the extension from the Visual Studio market place. The installation process is straight forward.</p><p><a href="https://marketplace.visualstudio.com/items?itemName=TechQuantum.DeepakAspNetVueJs">ASP.Net Core SPA with Vue Js - Visual Studio Marketplace</a></p><p>Now open Visual Studion 2019 or 2022, and search for the extension</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QB6PASwNWZownJ3tt8Hn6g.png" /></figure><p>Select the template and click next. Enter project name details and click Create</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/972/1*Ny3QvPrxgfMqdtpB9X7kuQ.png" /></figure><p>You will see the project is created and few example pages are already in place. Just build and run the project to see the examples in action.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*h7__qI5D9y_jc7Fwhfw7VA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/1*25CeZcix4xiBQ29mMz4dZw.png" /><figcaption>The home page is displayed with Hello World in blue color</figcaption></figure><p>Click on the Projects link to see the list of projects which are loaded via API calls. Also clicking on the one the project view link will show the details. This all are happening without any postback and view are rendered using the routes defined in the router.js file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nCRyH3fD9oUf9ciye3RbZQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*byndLbxKaHACcqnDm5j1jA.png" /></figure><p>In next blog I will give a better view on how to use the template by extending the example adding some more pages and login feature which will give a better usecase for using Vuex.Store to store session data.</p><p>Use it and if have any issue please raise here: <a href="https://github.com/deepakkumar1984/ASP.NET-Core-with-Vue-JS">https://github.com/deepakkumar1984/ASP.NET-Core-with-Vue-JS</a></p><p>Have fun!!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=22b9a79309dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Let machine play some music]]></title>
            <link>https://medium.com/analytics-vidhya/let-machine-play-some-music-1a86216df7a4?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a86216df7a4</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[csharp]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[music-generation]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Sun, 03 May 2020 12:24:06 GMT</pubDate>
            <atom:updated>2020-05-14T13:59:00.009Z</atom:updated>
            <content:encoded><![CDATA[<p>With advancement of AI it’s a no joke that machine will be able to play music. I am not sure that music will have emotions and compassion which might be easy to replace a human. Anyway in this blog I would be showing you how we can use deep learning to generate music. Of course you need to teach them first in order for it to produce on its own.</p><p>First we need some understanding of basic structure of a music. If we take an example of Piano here, the first thing even the most amateur musician will notice is an array of keys — some black and some white — that make different sounds or notes when struck. A combination of those notes, known as the chord on a piano is a minimum of 3 notes played together, sometimes more in some cases. Songs are written in keys, and what is known as the Key Signature, so that you can identify your root note to start. For instance, C Major chord is root note C (the root of the chord), 3rd interval note E, and 5th interval note G.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/435/0*xDP5PZwoPsKrR7dB.png" /></figure><p>Now in order to teach a machine to play music we need these musical notes to be fed into its brain. How do we get these notes??? This is where we are going to use music downloaded in MIDI formats. <strong>MIDI</strong> is a communication standard that allows digital music gear to speak the same language. <strong>MIDI</strong> is short for Musical Instrument Digital Interface. It’s a protocol that allows computers, musical instruments and other hardware to communicate.</p><p>Here is some examples of Piano music which we are going to use for training purpose: <a href="https://github.com/SciSharp/Keras.NET/tree/master/Examples/MusicGeneration/PianoDataset">https://github.com/SciSharp/Keras.NET/tree/master/Examples/MusicGeneration/PianoDataset</a></p><p>We are going to divide the cmplete code in 3 parts:</p><ol><li>Data Preparation</li><li>Model training</li><li>Music Generation</li></ol><p>Start by creating a new console project in Visual Studio. Add the following nuget packages to your project:</p><ol><li>Keras.NET: <a href="https://www.nuget.org/packages/Keras.NET">https://www.nuget.org/packages/Keras.NET</a></li><li>Melanchall.DryWetMidi: <a href="https://www.nuget.org/packages/Melanchall.DryWetMidi">https://www.nuget.org/packages/Melanchall.DryWetMidi</a></li></ol><p>Keras will be used to build deep learning model for training and predicting next note. Whereas Melanchall.DryWetMidi for data preparation and playing generated notes. Download all the midi files and place in a PianoDataset folder within the project. Create a new C# class “WavenetMusicGeneration.cs”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/359/0*d7I2zS7xDwyOTrtx.png" /></figure><h3>Data Preparation</h3><p>Open the “WavenetMusicGeneration.cs” and add the following fields.</p><pre>public class WavenetMusicGeneration<br> {<br>        static int no_of_timesteps = 32; //No. of notes to teach per step<br>        static NDarray train_x = null; // Training notes set<br>        static NDarray train_y = null; // Next note to play <br>        static int output = 127; //Max number of notes a piano have<br> }</pre><p>We need a function to read MIDI file and get list of the notes.</p><pre>private static Note[] ReadMidi(string file)<br> {<br>            Console.WriteLine(&quot;Loading music file: &quot; + file);<br>            var mf = MidiFile.Read(file);<br>            return mf.GetNotes().ToArray();<br>}</pre><p>The next function which we are going to use will be to read these downloaded training music files and combine the notes. Now these notes are in a string format so we are going to use the number version of the notes since a machine at the end understand the numbers.</p><pre>public static void PrepData()<br>{<br>            //notes array list declaration<br>            List&lt;Note[]&gt; notes_array = new List&lt;Note[]&gt;();<br><br>            //Get all the file list<br>            var files = Directory.GetFiles(&quot;./PianoDataset&quot;);<br><br>            //Loop through the files and read the notes, put them in the array<br>            foreach (var file in files)<br>            {<br>                notes_array.Add(ReadMidi(file));<br>            }<br><br>            //Show first 15 notes for the first music file<br>             Console.WriteLine(&quot;Displaying first 15 notes of first music&quot;);<br>            foreach (var n in notes_array[0].Take(15))<br>            {<br>                Console.Write(n.ToString() + &quot; &quot;);<br>            }<br><br>            //Declare X and Y which will hold the training set<br>            List&lt;float&gt; x = new List&lt;float&gt;();<br>            List&lt;float&gt; y = new List&lt;float&gt;();<br>           <br>            //Loop through the notes and prepare X and Y set.<br>            foreach (var notes in notes_array)<br>            {<br>                for (int i = 0; i &lt; notes.Length - no_of_timesteps; i++)<br>                {<br>                    var input = notes.Skip(i).Take(no_of_timesteps).Select(x =&gt; Convert.ToSingle(x.NoteNumber)).ToArray();<br>                    var output = Convert.ToSingle(notes[i + no_of_timesteps].NoteNumber);<br>                    x.AddRange(input);<br>                    y.Add(output);<br>                }<br>            }<br><br>            // Finally convert them to numpy array format for neural network training.<br>            train_x = np.array(x.ToArray(), dtype: np.float32).reshape(-1, 32);<br>            train_y = np.array(y.ToArray(), dtype: np.float32);<br>}</pre><p>Output of the prep function:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/519/0*EZZd_GopdrschK53.png" /></figure><h3>Teach a model</h3><p>Now comes the real part, to build a small section of brain and teach em music. We are going to use a variation (simpler version) of the WaveNet architecture. WaveNet is a deep neural network for generating raw audio. It was created by researchers at London-based artificial intelligence firm DeepMind. We are going to reuse the architecture to generate music :). You can google to get more info about the WaveNet, before proceeding further.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/0*2zY-FOwlvwTeqaoN.png" /></figure><p>Here is the code which will build the model and train it using the data set prepared before.</p><pre>public static void BuildAndTrain()<br>{<br>            //Model to hold the neural network architecture which in this case is WaveNet<br>            var model = new Sequential();<br>            // Starts with embedding layer<br>            model.Add(new Embedding(output, 100, input_length: 32));<br><br>            model.Add(new Conv1D(64, 3, padding: &quot;causal&quot;, activation: &quot;tanh&quot;));<br>            model.Add(new Dropout(0.2));<br>            model.Add(new MaxPooling1D(2));<br><br>            model.Add(new Conv1D(128, 3, activation: &quot;relu&quot;, dilation_rate: 2, padding: &quot;causal&quot;));<br>            model.Add(new Dropout(0.2));<br>            model.Add(new MaxPooling1D(2));<br><br>            model.Add(new Conv1D(256, 3, activation: &quot;relu&quot;, dilation_rate: 4, padding: &quot;causal&quot;));<br>            model.Add(new Dropout(0.2));<br>            model.Add(new MaxPooling1D(2));<br><br>            //model.Add(new Conv1D(256, 5, activation: &quot;relu&quot;));<br>            model.Add(new GlobalMaxPooling1D());<br><br>            model.Add(new Dense(256, activation: &quot;relu&quot;));<br>            model.Add(new Dense(output, activation: &quot;softmax&quot;));<br><br>            // Compile with Adam optimizer<br>            model.Compile(loss: &quot;sparse_categorical_crossentropy&quot;, optimizer: new Adam());<br>            model.Summary();<br><br>            // Callback to store the best trained model<br>            var mc = new ModelCheckpoint(&quot;best_model.h5&quot;, monitor: &quot;val_loss&quot;, mode: &quot;min&quot;, save_best_only: true, verbose: 1);<br><br>            //Method to actually train the model for 100 iteration<br>            var history = model.Fit(train_x, train_y, batch_size: 32, epochs: 100, validation_split: 0.25f, verbose: 1, callbacks: new Callback[] { mc });<br><br>            // Save the final trained model which we are going to use for prediction<br>            model.Save(&quot;last_epoch.h5&quot;);<br>}</pre><p>The training process is bit time consuming, but if you gave GPU then it makes it 10 times faster. Training outputs as below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/893/0*xoeF2aRgSnzqrKt-.png" /></figure><h3>Generate new music</h3><p>Now comes the fun part, we will generate music notes using this model. Use the below function to generate new music notes</p><pre>public static List&lt;int&gt; GenerateNewMusic(int n = 20)<br>{<br>            //Load the trained model<br>            var model = Model.LoadModel(&quot;last_epoch.h5&quot;);<br>            //Get a random 32 notes from the train set which we will use to get new notes<br>            var ind = np.random.randint(0, train_x.shape[0]);<br>            var random_music  = train_x[ind];<br><br>            //Build the prediction variable with sample 32 notes<br>            List&lt;float&gt; predictions = new List&lt;float&gt;();<br>            predictions.AddRange(random_music.GetData&lt;float&gt;());<br><br>            //Loop through N times which means N new notes, by default its 20<br>            for (int i = 0; i &lt; n; i++)<br>            {<br>                // Reshape to model adaptaed shape<br>                random_music = random_music.reshape(1, no_of_timesteps);<br>                //Predict the next best note to be played<br>                var prob = model.Predict(random_music)[0];<br>                var y_pred = np.argmax(prob, axis: 0);<br><br>                //Add the prediction and pick the last 32 to predict the next music note<br>                predictions.Add(y_pred.asscalar&lt;float&gt;());<br>                random_music = np.array(predictions.Skip(i + 1).ToArray());<br>            }<br><br>            //Finally skip the first 32 sample notes and return the rest N new predicted notes.<br>            return predictions.Skip(no_of_timesteps - 1).Select(x=&gt;(int)x).ToList();<br>}</pre><p>A function to play these notes. We are using default playback device on the computer and send the MidiEvent which will produce the Piano sound.</p><pre>private static void PlayNotes(List&lt;int&gt; notes)<br>{<br>            List&lt;List&lt;MidiEvent&gt;&gt; musicNotes = new List&lt;List&lt;MidiEvent&gt;&gt;();<br>            var playbackDevice = OutputDevice.GetAll().FirstOrDefault();<br>            foreach (var note in notes)<br>            {<br>                Note n = new Note(SevenBitNumber.Parse(note.ToString()));<br>                Console.Write(n + &quot; &quot;);<br>                playbackDevice.SendEvent(new NoteOffEvent(SevenBitNumber.Parse(note.ToString()), SevenBitNumber.MaxValue));<br>            }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/556/1*EJ_bQ-LEHmBH0UNW0YJzMw.png" /></figure><p>Final Main function which calls all these above functions:</p><pre>static void Main(string[] args)<br>{<br>            WavenetMusicGeneration.PrepData();<br>            WavenetMusicGeneration.BuildAndTrain();<br>            var notes = WavenetMusicGeneration.GenerateNewMusic(20);<br>            Console.WriteLine(&quot;\n\nPlaying auto generated music....\n&quot;);<br>            PlayNotes(notes);<br>}</pre><p>Awesome, right? But your learning doesn’t stop here. There are plenty of ways to improve the performance of the model even further:</p><ul><li>We can fine-tune a pre-trained model to build a robust system</li><li>Collect as much as training data as you can since the deep learning model generalizes well on the larger datasets</li></ul><p>Example code: <a href="https://github.com/SciSharp/Keras.NET/tree/master/Examples/MusicGeneration">https://github.com/SciSharp/Keras.NET/tree/master/Examples/MusicGeneration</a></p><p><em>Originally published at </em><a href="https://www.tech-quantum.com/let-machine-play-some-music/"><em>https://www.tech-quantum.com</em></a><em> on May 3, 2020.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a86216df7a4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/analytics-vidhya/let-machine-play-some-music-1a86216df7a4">Let machine play some music</a> was originally published in <a href="https://medium.com/analytics-vidhya">Analytics Vidhya</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep learning using popular MxNet for C# lovers]]></title>
            <link>https://deepakbattini.medium.com/deep-learning-using-popular-mxnet-for-c-lovers-88e357a5f4b0?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/88e357a5f4b0</guid>
            <category><![CDATA[mxnet]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Fri, 03 Apr 2020 01:49:29 GMT</pubDate>
            <atom:updated>2020-04-04T11:49:10.446Z</atom:updated>
            <content:encoded><![CDATA[<p>Apache MXNet (incubating) is a deep learning framework designed for both <em>efficiency</em> and <em>flexibility</em>. It allows you to <em>mix</em> <a href="https://mxnet.apache.org/api/architecture/program_model">symbolic and imperative programming</a> to <em>maximize</em> efficiency and productivity. At its core, MXNet contains a dynamic dependency scheduler that automatically parallelizes both symbolic and imperative operations on the fly. A graph optimization layer on top of that makes symbolic execution fast and memory efficient. MXNet is portable and lightweight, scaling effectively to multiple GPUs and multiple machines.</p><h3>MxNet.Sharp</h3><p>MxNet.Sharp is a CSharp binding coving all the Imperative, Symbolic and Gluon API’s with an easy to use interface. The Gluon library in Apache MXNet provides a clear, concise, and simple API for deep learning. It makes it easy to prototype, build, and train deep learning models without sacrificing training speed.</p><h3>High Level Arch</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/903/0*XxxbC-iM1kfw53rI.PNG" /></figure><h3>Nuget</h3><p>Install the package: Install-Package MxNet.Sharp</p><p><a href="https://www.nuget.org/packages/MxNet.Sharp">https://www.nuget.org/packages/MxNet.Sharp</a></p><p>Add the MxNet redistributed package available as per below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/982/1*DXkEjrvq00gNHcYGVeHmkw.png" /></figure><p>Important: Make sure your installed CUDA version matches the CUDA version in the nuget package.</p><p>Check your CUDA version with the following command:</p><pre>nvcc --version</pre><p>You can either upgrade your CUDA install or install the MXNet package that supports your CUDA version.</p><p>MxNet Version Build: <a href="https://github.com/apache/incubator-mxnet/releases/tag/1.5.0">https://github.com/apache/incubator-mxnet/releases/tag/1.5.0</a></p><h3>Gluon MNIST Example</h3><p>Demo as per: <a href="https://mxnet.apache.org/api/python/docs/tutorials/packages/gluon/image/mnist.html">https://mxnet.apache.org/api/python/docs/tutorials/packages/gluon/image/mnist.html</a></p><pre>var mnist = TestUtils.GetMNIST(); //Get the MNIST dataset, it will download if not found<br>var batch_size = 200; //Set training batch size<br>var train_data = new NDArrayIter(mnist[&quot;train_data&quot;], mnist[&quot;train_label&quot;], batch_size, true);<br>var val_data = new NDArrayIter(mnist[&quot;test_data&quot;], mnist[&quot;test_label&quot;], batch_size);</pre><pre>// Define simple network with dense layers<br>var net = new Sequential();<br>net.Add(new Dense(128, ActivationType.Relu));<br>net.Add(new Dense(64, ActivationType.Relu));<br>net.Add(new Dense(10));</pre><pre>//Set context, multi-gpu supported<br>var gpus = TestUtils.ListGpus();<br>var ctx = gpus.Count &gt; 0 ? gpus.Select(x =&gt; Context.Gpu(x)).ToArray() : new[] {Context.Cpu(0)};</pre><pre>//Initialize the weights<br>net.Initialize(new Xavier(magnitude: 2.24f), ctx);</pre><pre>//Create the trainer with all the network parameters and set the optimizer<br>var trainer = new Trainer(net.CollectParams(), new SGD(learning_rate: 0.02f));</pre><pre>var epoch = 10;<br>var metric = new Accuracy(); //Use Accuracy as the evaluation metric.<br>var softmax_cross_entropy_loss = new SoftmaxCELoss();<br>float lossVal = 0; //For loss calculation<br>for (var iter = 0; iter &lt; epoch; iter++)<br>{<br>    var tic = DateTime.Now;<br>    // Reset the train data iterator.<br>    train_data.Reset();<br>    lossVal = 0;</pre><pre>    // Loop over the train data iterator.<br>    while (!train_data.End())<br>    {<br>        var batch = train_data.Next();</pre><pre>        // Splits train data into multiple slices along batch_axis<br>        // and copy each slice into a context.<br>        var data = Utils.SplitAndLoad(batch.Data[0], ctx, batch_axis: 0);</pre><pre>        // Splits train labels into multiple slices along batch_axis<br>        // and copy each slice into a context.<br>        var label = Utils.SplitAndLoad(batch.Label[0], ctx, batch_axis: 0);</pre><pre>        var outputs = new NDArrayList();</pre><pre>        // Inside training scope<br>        using (var ag = Autograd.Record())<br>        {<br>            outputs = Enumerable.Zip(data, label, (x, y) =&gt;<br>            {<br>                var z = net.Call(x);</pre><pre>                // Computes softmax cross entropy loss.<br>                NDArray loss = softmax_cross_entropy_loss.Call(z, y);</pre><pre>                // Backpropagate the error for one iteration.<br>                loss.Backward();<br>                lossVal += loss.Mean();<br>                return z;<br>            }).ToList();<br>        }</pre><pre>        // Updates internal evaluation<br>        metric.Update(label, outputs.ToArray());</pre><pre>        // Make one step of parameter update. Trainer needs to know the<br>        // batch size of data to normalize the gradient by 1/batch_size.<br>        trainer.Step(batch.Data[0].Shape[0]);<br>    }</pre><pre>    var toc = DateTime.Now;</pre><pre>    // Gets the evaluation result.<br>    var (name, acc) = metric.Get();</pre><pre>    // Reset evaluation result to initial state.<br>    metric.Reset();<br>    Console.Write($&quot;Loss: {lossVal} &quot;);<br>    Console.WriteLine($&quot;Training acc at epoch {iter}: {name}={(acc * 100).ToString(&quot;0.##&quot;)}%, Duration: {(toc - tic).TotalSeconds.ToString(&quot;0.#&quot;)}s&quot;);<br>}</pre><p>Project URL, please show your support by starring the project: <a href="https://github.com/SciSharp/MxNet.Sharp">https://github.com/SciSharp/MxNet.Sharp</a></p><p>Will be adding mode example post :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=88e357a5f4b0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Keras.NET — high-level neural networks API in C#]]></title>
            <link>https://medium.com/scisharp/introducing-keras-net-high-level-neural-networks-api-in-c-4695f19d3f77?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/4695f19d3f77</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[tensorflow]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Fri, 21 Jun 2019 08:26:09 GMT</pubDate>
            <atom:updated>2019-06-21T10:51:48.856Z</atom:updated>
            <cc:license>https://creativecommons.org/licenses/by-nc-sa/4.0/</cc:license>
            <content:encoded><![CDATA[<h3>Introducing Keras.NET — high-level neural networks API in C#</h3><h3>Keras.NET</h3><p>Keras.NET is a high-level neural networks API, written in C# with Python Binding and capable of running on top of TensorFlow, CNTK, or Theano. It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.</p><p>Use Keras if you need a deep learning library that:</p><p>Allows for easy and fast prototyping (through user friendliness, modularity, and extensibility). Supports both convolutional networks and recurrent networks, as well as combinations of the two. Runs seamlessly on CPU and GPU.</p><figure><img alt="Image result for keras" src="https://cdn-images-1.medium.com/proxy/1*94aYxMPfqqQsv4AJ8A_5Lw.jpeg" /></figure><h3>Keras.NET is using:</h3><ul><li><a href="https://github.com/SciSharp/Numpy.NET">Numpy.NET</a></li><li><a href="https://github.com/henon/Python.Included">Python.Included</a></li></ul><h3>Prerequisite</h3><ul><li>Python 3.6, Link: <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></li><li>Install keras, numpy and one of the backend (Tensorflow/CNTK/Theano). Please see on how to configure: <a href="https://keras.io/backend/">https://keras.io/backend/</a></li></ul><h3>Nuget</h3><p>Install from nuget: <a href="https://www.nuget.org/packages/Keras.NET">https://www.nuget.org/packages/Keras.NET</a></p><pre>Install-Package Keras.NET</pre><pre>dotnet add package Keras.NET</pre><h3>Example with XOR sample</h3><pre>//Load train data<br>NDarray x = np.array(new float[,] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } });<br>NDarray y = np.array(new float[] { 0, 1, 1, 0 });</pre><pre>//Build sequential model<br>var model = new Sequential();<br>model.Add(new Dense(32, activation: &quot;relu&quot;, input_shape: new Shape(2)));<br>model.Add(new Dense(64, activation: &quot;relu&quot;));<br>model.Add(new Dense(1, activation: &quot;sigmoid&quot;));</pre><pre>//Compile and train<br>model.Compile(optimizer:&quot;sgd&quot;, loss:&quot;binary_crossentropy&quot;, metrics: new string[] { &quot;accuracy&quot; });<br>model.Fit(x, y, batch_size: 2, epochs: 1000, verbose: 1);</pre><pre>//Save model and weights<br>string json = model.ToJson();<br>File.WriteAllText(&quot;model.json&quot;, json);<br>model.SaveWeight(&quot;model.h5&quot;);</pre><pre>//Load model and weight<br>var loaded_model = Sequential.ModelFromJson(File.ReadAllText(&quot;model.json&quot;));<br>loaded_model.LoadWeight(&quot;model.h5&quot;);</pre><p><strong>Output:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/963/0*vvygrPyuUf92nLo_.PNG" /></figure><h3>MNIST CNN Example</h3><p>Python example taken from: <a href="https://keras.io/examples/mnist_cnn/">https://keras.io/examples/mnist_cnn/</a></p><pre>int batch_size = 128;<br>int num_classes = 10;<br>int epochs = 12;</pre><pre>// input image dimensions<br>int img_rows = 28, img_cols = 28;</pre><pre>Shape input_shape = null;</pre><pre>// the data, split between train and test sets<br>var ((x_train, y_train), (x_test, y_test)) = MNIST.LoadData();</pre><pre>if(K.ImageDataFormat() == &quot;channels_first&quot;)<br>{<br>    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols);<br>    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols);<br>    input_shape = (1, img_rows, img_cols);<br>}<br>else<br>{<br>    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1);<br>    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1);<br>    input_shape = (img_rows, img_cols, 1);<br>}</pre><pre>x_train = x_train.astype(np.float32);<br>x_test = x_test.astype(np.float32);<br>x_train /= 255;<br>x_test /= 255;<br>Console.WriteLine(&quot;x_train shape: &quot; + x_train.shape);<br>Console.WriteLine(x_train.shape[0] + &quot; train samples&quot;);<br>Console.WriteLine(x_test.shape[0] + &quot; test samples&quot;);</pre><pre>// convert class vectors to binary class matrices<br>y_train = Utils.ToCategorical(y_train, num_classes);<br>y_test = Utils.ToCategorical(y_test, num_classes);</pre><pre>// Build CNN model<br>var model = new Sequential();<br>model.Add(new Conv2D(32, kernel_size: (3, 3).ToTuple(),<br>                        activation: &quot;relu&quot;,<br>                        input_shape: input_shape));<br>model.Add(new Conv2D(64, (3, 3).ToTuple(), activation: &quot;relu&quot;));<br>model.Add(new MaxPooling2D(pool_size: (2, 2).ToTuple()));<br>model.Add(new Dropout(0.25));<br>model.Add(new Flatten());<br>model.Add(new Dense(128, activation: &quot;relu&quot;));<br>model.Add(new Dropout(0.5));<br>model.Add(new Dense(num_classes, activation: &quot;softmax&quot;));</pre><pre>model.Compile(loss: &quot;categorical_crossentropy&quot;,<br>    optimizer: new Adadelta(), metrics: new string[] { &quot;accuracy&quot; });</pre><pre>model.Fit(x_train, y_train,<br>            batch_size: batch_size,<br>            epochs: epochs,<br>            verbose: 1,<br>            validation_data: new NDarray[] { x_test, y_test });<br>var score = model.Evaluate(x_test, y_test, verbose: 0);<br>Console.WriteLine(&quot;Test loss:&quot;, score[0]);<br>Console.WriteLine(&quot;Test accuracy:&quot;, score[1]);</pre><p><strong>Output</strong></p><p>Reached 98% accuracy within 3 epoches.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EiaOuu2wt2ydqtEV.PNG" /></figure><p>Here is the project: <a href="https://github.com/SciSharp/Keras.NET/">https://github.com/SciSharp/Keras.NET/</a></p><p>Documentation: <a href="https://scisharp.github.io/Keras.NET/">https://scisharp.github.io/Keras.NET/</a></p><p>Now run your keras models in .NET. Will add more blogs with more examples. Stay tuned :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4695f19d3f77" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/introducing-keras-net-high-level-neural-networks-api-in-c-4695f19d3f77">Introducing Keras.NET — high-level neural networks API in C#</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Train your own handwritten digit recognizer in C# .NET]]></title>
            <link>https://medium.com/scisharp/train-your-own-handwritten-digit-recognizer-in-c-net-e78320329359?source=rss-2bcce0e423a9------2</link>
            <guid isPermaLink="false">https://medium.com/p/e78320329359</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[keras]]></category>
            <category><![CDATA[mnist]]></category>
            <dc:creator><![CDATA[Deepak Battini]]></dc:creator>
            <pubDate>Sat, 25 May 2019 06:00:50 GMT</pubDate>
            <atom:updated>2019-06-25T10:24:21.616Z</atom:updated>
            <content:encoded><![CDATA[<h3>Train your own handwritten digit recognizer in C# .NET</h3><p>Convolutional neural networks (CNNs) are the current state-of-the-art model architecture for image classification tasks. CNNs apply a series of filters to the raw pixel data of an image to extract and learn higher-level features, which the model can then use for classification.</p><p>This post we will take a very common example of CNN to recognize hand written digit. We will train a deep learning model in C# and use that trained model to predict the hand written digit. We will be using <a href="https://www.nuget.org/packages/Keras.NET">Keras.NET</a> in order to write our own model and train it with standard MNIST dataset which is a collection of 60,000 training images and 10,000 testing images taken from American Census Bureau employees and American high school students.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/660/0*h8S6SmPrW4A7m1Ng" /></figure><p>An example of a digit from MNIST is below. It a gray scale image of size 28×28.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/245/0*ZbyOMbQEV732RVd-" /></figure><h3>Keras.NET Setup</h3><p>Keras.NET needs Python, we will start with some prerequisite:</p><ol><li>Download python executable and install it. Here is the link: <a href="https://www.python.org/ftp/python/3.6.8/python-3.6.8-amd64.exe">https://www.python.org/ftp/python/3.6.8/python-3.6.8-amd64.exe</a></li><li>Once installed, open command prompt and run python which will load python successfully. Exit the command and lets start installing keras packages.</li><li>Run the following the command to install keras: pip install keras</li><li>Keras need backend which can be one of the following: tensorflow/cntk/theano/plaidml. Let’s use tensorflow, by running command “pip install tensorflow”. If you have GPU setup with proper CUDA installed, you can use tensorflow-gpu</li></ol><p>All good, once you done the setup, you can check the setup by running: python -m “keras”</p><h3>Implementation</h3><p>Let’s start by creating a new .NET core console project “Basic MNIST”. From the nuget package manager add the reference of Keras.NET. The library is built on top of Python giving an ability to the .NET developers to build and execute Keras code in C# which is more structured. Under the hood, the library will communicate with keras library installed.</p><p>In the main method of Program.cs, declare the following variable:</p><pre>int batch_size = 128; //Training batch size<br>int num_classes = 10; //No. of classes<br>int epochs = 12; //No. of epoches we will train</pre><pre>// input image dimensions<br>int img_rows = 28, img_cols = 28;</pre><pre>// Declare the input shape for the network<br>Shape input_shape = null;</pre><p>We have a helper method in Keras which will download the MNIST dataset and give you the Numpy array format. Based on the data format specified, we will declare the input_shape (N, H, W, C), this case it will be (1, 28, 28, 1) for channel last</p><pre>// Load the MNIST dataset into Numpy array<br>var ((x_train, y_train), (x_test, y_test)) = MNIST.LoadData();</pre><pre>//Check if its channel fist or last and rearrange the dataset accordingly<br>if(K.ImageDataFormat() == &quot;channels_first&quot;)<br>{<br> x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols);<br> x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols);<br> input_shape = (1, img_rows, img_cols);<br>}<br>else<br>{<br> x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1);<br> x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1);<br> input_shape = (img_rows, img_cols, 1);<br>}</pre><p>Normalize the input image data</p><pre>//Normalize the input data<br>x_train = x_train.astype(np.float32);<br>x_test = x_test.astype(np.float32);<br>x_train /= 255;<br>x_test /= 255;<br>Console.WriteLine(&quot;x_train shape: &quot; + x_train.shape);<br>Console.WriteLine(x_train.shape[0] + &quot; train samples&quot;);<br>Console.WriteLine(x_test.shape[0] + &quot; test samples&quot;);</pre><p>The expected values are numbers like 3, 5, 1 which need to be converted to the binary of base pair 10. Use the following below:</p><pre>// Convert class vectors to binary class matrices<br>y_train = Util.ToCategorical(y_train, num_classes);<br>y_test = Util.ToCategorical(y_test, num_classes);</pre><p>Build a CNN model, which is a combination of Convolution, Pooling and Dense layers</p><pre>// Build CNN model<br>var model = new Sequential();<br>model.Add(new Conv2D(32, kernel_size: (3, 3).ToTuple(),<br>                 activation: &quot;relu&quot;,<br>     input_shape: input_shape));<br>model.Add(new Conv2D(64, (3, 3).ToTuple(), activation: &quot;relu&quot;));<br>model.Add(new MaxPooling2D(pool_size: (2, 2).ToTuple()));<br>model.Add(new Dropout(0.25));<br>model.Add(new Flatten());<br>model.Add(new Dense(128, activation: &quot;relu&quot;));<br>model.Add(new Dropout(0.5));<br>model.Add(new Dense(num_classes, activation: &quot;softmax&quot;));</pre><p>Compile the model with AdaDelta optimizer and categorial cross-entropy loss, We will use an accuracy metric to measure the performance.</p><pre>//Compile with loss, metrics and optimizer<br>model.Compile(loss: &quot;categorical_crossentropy&quot;,<br>     optimizer: new Adadelta(), metrics: new string[] { &quot;accuracy&quot; });</pre><pre>//Train the model<br>model.Fit(x_train, y_train,<br>   batch_size: batch_size,<br>   epochs: epochs,<br>   verbose: 1,<br>   validation_data: new NDarray[] { x_test, y_test });</pre><p>Once the model is trained, we can evaluate against test data and finally save it to HDF5 and Tensorflow JS format. We will later use the Tensorflow JS format to run the model on the web page.</p><pre>//Score the model for performance<br>var score = model.Evaluate(x_test, y_test, verbose: 0);<br>Console.WriteLine(&quot;Test loss:&quot; + score[0]);<br>Console.WriteLine(&quot;Test accuracy:&quot; + score[1]);</pre><pre>// Save the model to HDF5 format which can be loaded later or ported to other application<br>model.Save(&quot;model.h5&quot;);<br>// Save it to Tensorflow JS format and we will test it in browser.<br>model.SaveTensorflowJSFormat(&quot;./&quot;);</pre><p>Below is how the training progresses, the accuracy of 98% is achieved within 2 epoch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*gpoEY4MZnTmp2dPL" /></figure><p>Here is the keras playground for MNIST which is using the trained model. <a href="https://kerasdotnet.azurewebsites.net/MNIST">https://kerasdotnet.azurewebsites.net/MNIST</a></p><p>Just draw the number and click on Recognize, the model will predict the number for you.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*1opxr64wU441UUSd" /></figure><p>Please take a spin trying out Keras.NET and let me know how it goes. I will keep you posted with more examples. So stay tuned 🙂</p><p>Project URL: <a href="https://github.com/SciSharp/Keras.NET">https://github.com/SciSharp/Keras.NET</a></p><p><em>Originally published at </em><a href="https://www.tech-quantum.com/train-your-own-handwritten-digit-recognizer-in-c-net/"><em>https://www.tech-quantum.com</em></a><em> on May 25, 2019.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e78320329359" width="1" height="1" alt=""><hr><p><a href="https://medium.com/scisharp/train-your-own-handwritten-digit-recognizer-in-c-net-e78320329359">Train your own handwritten digit recognizer in C# .NET</a> was originally published in <a href="https://medium.com/scisharp">SciSharp STACK</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>