OllamaSharp Documentation

repository·main·Indexed 23 days ago

https://github.com/awaescher/ollamasharp

.NET bindings for the Ollama API that enable interaction with Ollama locally or remotely. It supports chat, embeddings, model management, streaming, and tool calling. The library implements IChatClient and IEmbeddingGenerator<string, Embedding<float>> from Microsoft.Extensions.AI and is recommended for use with Semantic Kernel. Key features include a Chat class for multi-turn conversations with automatic history tracking, Native AOT support via JsonSerializerContext, and support for multi-modal models and reasoning tokens.

Tokens
11.6K
Snippets
47
Records
53
Agent score
78%

What's inside OllamaSharp

  1. What is OllamaSharp

    main
    OllamaSharp provides .NET bindings for the Ollama API, allowing you to interact with local or remote Ollama servers. It simplifies common tasks by providing asynchronous streaming, progress reporting, and convenience classes for model management and chat interactions.
  2. Handle reasoning/thinking tokens in models

    main

    For reasoning models (like deepseek-r1 or phi4-reasoning), you can enable thinking mode via the Think property. When enabled, internal reasoning is emitted through the OnThink event and is kept separate from the visible answer.

    Think accepts a ThinkValue struct for budget control:

    • ThinkValue.High: Maximum reasoning effort.
    • ThinkValue.Medium: Balanced reasoning.
    • ThinkValue.Low: Minimal reasoning.
    var chat = new Chat(ollama) { Think = ThinkValue.High };
    
    chat.OnThink += (_, thoughts) => Console.Write($"[thinking] {thoughts}");
    
    await foreach (var token in chat.SendAsync("What is the square root of 144?"))
        Console.Write(token);
  3. Use the `Chat` class for conversational AI

    main

    The Chat class is the recommended high-level interface for conversational use cases. It automatically manages message history (chat.Messages) so the model maintains context across multiple turns. Each call to SendAsync appends both the user's message and the assistant's response to the history.

    var ollama = new OllamaApiClient("http://localhost:11434", "qwen3.5:35b-a3b");
    var chat = new Chat(ollama);
    
    while (true)
    {
        Console.Write("You: ");
        var message = Console.ReadLine()!;
    
        Console.Write("Assistant: ");
        await foreach (var token in chat.SendAsync(message))
            Console.Write(token);
    
        Console.WriteLine();
    }
  4. Use OllamaSharp with Microsoft.Extensions.AI

    main

    OllamaSharp implements the IChatClient and IEmbeddingGenerator<string, Embedding<float>> interfaces from the Microsoft.Extensions.AI library. This allows you to use Ollama as a provider in applications designed for unified AI abstractions.

    Note that while OllamaApiClient implements these interfaces, casting to IChatClient will hide Ollama-specific methods available in the native IOllamaApiClient interface.

    // Requires package: Microsoft.Extensions.AI.Abstractions
    
    private static IChatClient CreateChatClient(Arguments arguments)
    {
      if (arguments.Provider.Equals("ollama", StringComparison.OrdinalIgnoreCase))
        return new OllamaApiClient(arguments.Uri, arguments.Model);
      else
        return new OpenAIChatClient(new OpenAI.OpenAIClient(arguments.ApiKey), arguments.Model);
    }
  5. Key capabilities of OllamaSharp

    main

    OllamaSharp offers several advanced features for working with LLMs:

    • Full Ollama API coverage: Every endpoint is wrapped in an async, streaming-capable method.
    • Chat conversations: The Chat class manages message history, tool calls, and thinking tokens across turns.
    • Tool / function calling: Use the [OllamaTool] attribute to define tools; a source generator handles the implementation details.
    • Microsoft.Extensions.AI integration: Implements IChatClient and IEmbeddingGenerator<string, Embedding<float>> for compatibility with the M.E.AI ecosystem.
    • Model management: Support for pull, push, copy, delete, show, and list operations.
    • Multi-modal support: Ability to send images to vision-capable models.
    • Structured output: Support for requesting responses in JSON or JSON Schema formats.
    • Reasoning models: Capability to surface "think tokens" from models like DeepSeek R1 and Qwen3.
    • Native AOT support: Opt-in support via a custom JsonSerializerContext.
    • MCP integration: Bridge Model Context Protocol tools into OllamaSharp using a companion package.
  6. Build interactive chats with the Chat class

    main

    The Chat class manages conversation state by automatically tracking message history (including roles and tool calls) across turns. This ensures the model maintains context throughout an interactive session. You can use SendAsync to send user messages and receive a stream of answer tokens.

    // The chat object tracks history automatically via the Messages property
    var chat = new Chat(ollama);
    
    while (true)
    {
        var message = Console.ReadLine();
        await foreach (var answerToken in chat.SendAsync(message))
            Console.Write(answerToken);
    }
  7. How the Chat class works for conversational applications

    main

    The Chat class is the recommended abstraction for building conversational/multi-turn applications.

    Key features:

    • Automatic History Tracking: It automatically tracks the full message history, including roles and tool calls/results, across turns.
    • Context Management: Because it tracks history, the model always has the full context of the conversation.
    • Streaming: SendAsync returns an IAsyncEnumerable for real-time response streaming.
    // messages including their roles and tool calls will automatically be tracked within the chat object
    // and are accessible via the Messages property
    
    var chat = new Chat(ollama);
    
    while (true)
    {
        var message = Console.ReadLine();
        await foreach (var answerToken in chat.SendAsync(message))
            Console.Write(answerToken);
    }
    var chat = new Chat(ollama);
    
    while (true)
    {
        var message = Console.ReadLine();
        await foreach (var answerToken in chat.SendAsync(message))
            Console.Write(answerToken);
    }
  8. Connect to Ollama cloud models (Ollama Turbo)

    main

    To use Ollama cloud models, initialize the OllamaApiClient using an HttpClient that already contains your required authentication headers.

    var client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:11434");
    client.DefaultRequestHeaders.Add(/* your api key here */);
    
    var ollama = new OllamaApiClient(client);
  9. Work with blobs for custom models

    main

    When creating models from local files, you must first upload the files as blobs to the Ollama server.

    1. Check/Upload Blob: Use IsBlobExistsAsync(digest) to check if a file with a specific SHA256 digest already exists. If not, use PushBlobAsync(digest, bytes) to upload the file.
    2. Reference Blob: In your CreateModelRequest, use the Files dictionary to map the local filename to its server-side digest.
    var digest = "sha256:29fdb92e57cf...";
    
    // 1. Upload blob if it doesn't exist
    if (!await ollama.IsBlobExistsAsync(digest))
    {
        var bytes = await File.ReadAllBytesAsync("my-model-weights.bin");
        await ollama.PushBlobAsync(digest, bytes);
    }
    
    // 2. Create model referencing the blob
    await foreach (var status in ollama.CreateModelAsync(new CreateModelRequest
    {
        Model = "my-local-model",
        Files = new Dictionary<string, string> { ["my-model-weights.bin"] = digest },
    }))
    {
        Console.WriteLine(status?.Status);
    }
  10. Use tools (function calling) with `Chat`

    main

    To use tools, define a class with methods decorated with the [OllamaTool] attribute (requires a source generator). Pass instances of these tool classes to SendAsync to enable function calling.

    public class MyTools
    {
        [OllamaTool]
        public static string GetWeather(string city) => $"Sunny and 22°C in {city}.";
    }
    
    var chat = new Chat(ollama);
    await foreach (var token in chat.SendAsync("What's the weather in Berlin?", [new GetWeatherTool()]))
        Console.Write(token);
  11. Start talking to Ollama with OllamaApiClient and Chat

    main

    To interact with Ollama, initialize an OllamaApiClient with the Ollama service URI and the desired model name. You can then use a Chat object to manage a conversation. The Chat object automatically tracks messages (including roles and tool calls) in its Messages property. Use chat.SendAsync(message) to stream responses from the model.

    using OllamaSharp;
    
    var uri = new Uri("http://localhost:11434");
    var ollama = new OllamaApiClient(uri, "qwen3.5:35b-a3b");
    
    // messages including their roles and tool calls will automatically
    // be tracked within the chat object and are accessible via the Messages property
    var chat = new Chat(ollama);
       
    Console.WriteLine("You're now talking with Ollama. Hit Ctrl+C to exit.");
    
    while (true)
    {
        Console.Write("You: ");
        var message = Console.ReadLine();
    
        Console.Write("Assistant: ");
        await foreach (var stream in chat.SendAsync(message))
            Console.Write(stream);
    
        Console.WriteLine("");
    }
  12. Configure Native AOT support for OllamaSharp

    main

    OllamaSharp supports .NET Native AOT (Ahead-of-Time) compilation. By default, it uses standard System.Text.Json serialization which is compatible with most scenarios. However, for Native AOT environments, you must provide a custom JsonSerializerContext that explicitly includes all types used in serialization (including standard OllamaSharp types, custom message types, and third-party library types like those from Semantic Kernel).

    // 1. Define a custom context with all required types
    [JsonSerializable(typeof(ChatRequest))]
    [JsonSerializable(typeof(ChatResponseStream))]
    [JsonSerializable(typeof(ChatDoneResponseStream))]
    [JsonSerializable(typeof(List<MyCustomType>))]
    public partial class MyCustomJsonContext : JsonSerializerContext
    {
    }
    
    // 2. Pass the context to the OllamaApiClient configuration
    var config = new OllamaApiClient.Configuration
    {
        Uri = new Uri("http://localhost:11434"),
        Model = "qwen3.5:35b-a3b",
        JsonSerializerContext = MyCustomJsonContext.Default
    };
    var client = new OllamaApiClient(config);