OllamaSharp : lier une application .NET à un serveur Ollama sans écrire le client HTTP
The easiest way to use Ollama in .NET
En bref
- De quoi s’agit-il ?
- OllamaSharp est un ensemble de bindings C# pour l'API Ollama, publié sous licence MIT et couvrant l'ensemble des endpoints documentés. Le paquet est simple à mettre en route, mais il suppose un serveur Ollama déjà joignable et ne masque pas les compromis de l'inférence locale.
- À qui s’adresse-t-il ?
- OllamaSharp convient aux équipes .NET qui ont déjà un serveur Ollama en fonctionnement et qui veulent éviter d'écrire leur propre client HTTP. Il ne convient pas à celles qui cherchent une inférence embarquée sans processus externe, ni un fournisseur unique abstrait sur plusieurs backends.
- Puis-je l’utiliser commercialement ?
- Oui. MIT est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 54 jours.
- En quel langage est-il écrit ?
- Principalement C#, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème concret : parler à Ollama depuis du code C#
Ollama expose une API HTTP locale, généralement sur http://localhost:11434. Un développeur .NET qui veut l'utiliser doit sérialiser des requêtes JSON, gérer les réponses en flux, suivre les identifiants de conversation et redémarrer le traitement quand le format change. OllamaSharp remplace ce travail par des méthodes awaitables. Le README résume l'ambition en une phrase : fournir des bindings .NET pour l'API Ollama, en local comme à distance. Le public visé est donc précis : des applications .NET qui consomment un serveur Ollama existant, pas des applications qui embarquent un moteur d'inférence. Si vous n'avez pas de serveur Ollama à joindre, la bibliothèque ne vous sert à rien. Elle ne télécharge pas de poids de modèle par elle-même, elle demande au serveur de le faire.
Ce que le client enveloppe réellement
Le point d'entrée est la classe OllamaApiClient. Le README indique qu'elle couvre chaque endpoint de l'API Ollama : conversations, embeddings, liste des modèles, pull, push, copie, suppression, inspection. Chaque endpoint devient une méthode awaitable, et les réponses longues sont exposées en flux. L'initialisation tient en deux lignes : une Uri vers le serveur, puis l'affectation de la propriété SelectedModel. Cette propriété détermine le modèle utilisé par les opérations suivantes, ce qui évite de répéter le nom du modèle à chaque appel. Deux méthodes illustrent le style : ListLocalModelsAsync renvoie les modèles présents sur le serveur, et PullModelAsync renvoie une séquence d'objets de statut contenant un pourcentage et un libellé, ce que le README montre dans une boucle await foreach. Le streaming n'est pas un mode optionnel ajouté après coup : il est le mode de retour par défaut de GenerateAsync et de Chat.SendAsync.
GenerateAsync et Chat : deux niveaux de responsabilité
GenerateAsync correspond à l'endpoint /api/generate. Le README le présente comme adapté aux complétions à tour unique, sans contexte. Vous lui passez une chaîne, vous recevez des fragments de réponse. Aucun historique n'est conservé entre deux appels. La classe Chat joue un rôle différent. Elle conserve l'historique complet des messages, y compris les appels d'outils et leurs résultats, et l'expose via une propriété Messages. C'est cette conservation qui distingue les deux usages : avec GenerateAsync, la mémoire de la conversation est votre problème ; avec Chat, elle est déléguée à l'objet. Ce choix a un coût direct. Une conversation longue fait grossir la liste de messages envoyée au serveur à chaque tour, et donc le temps de traitement comme la consommation de contexte du modèle. Le README ne décrit pas de mécanisme de troncature ou de résumé automatique. Il faut donc gérer soi-même la taille de l'historique si les sessions s'allongent.
Mise en route : paquet, URI, modèle
L'installation se fait depuis NuGet, sous le nom OllamaSharp. Le README donne l'exemple minimal : créer une Uri sur http://localhost:11434, instancier OllamaApiClient avec cette Uri, puis définir SelectedModel sur un nom de modèle, par exemple qwen3.5:35b-a3b. À partir de là, les appels se font directement. Pour lister les modèles locaux, une seule ligne suffit : await ollama.ListLocalModelsAsync(). Pour récupérer un modèle avec retour de progression, le README montre une boucle await foreach sur ollama.PullModelAsync, avec affichage du pourcentage et du statut à chaque itération. Pour une complétion simple, await foreach sur ollama.GenerateAsync, en écrivant stream.Response. Pour une conversation interactive, new Chat(ollama) puis await foreach sur chat.SendAsync(message). Le README mentionne aussi le prompt système, l'envoi d'images pour les modèles de vision, la sortie JSON structurée et le mode réflexion, en renvoyant à la documentation dédiée pour le détail.
Modèles cloud et clé d'API
Le client ne se limite pas à un serveur local. Le README indique qu'OllamaSharp fonctionne avec les modèles cloud d'Ollama, et donne la marche à suivre : utiliser le constructeur qui accepte un HttpClient, définir BaseAddress, puis ajouter la clé d'API dans DefaultRequestHeaders. Ce point mérite attention. La clé circule alors en en-tête par défaut de toutes les requêtes émises par ce HttpClient. Si l'instance est partagée avec d'autres appels, l'en-tête suit. Le README n'entre pas dans ce détail et se contente de montrer l'ajout. C'est un cas où la brièveté de la documentation laisse la décision de cloisonnement au développeur.
Intégration Microsoft.Extensions.AI et appels d'outils
OllamaApiClient implémente deux interfaces de Microsoft.Extensions.AI : IChatClient pour l'inférence et IEmbeddingGenerator<string, Embedding<float>> pour les embeddings. Le README précise que le même objet peut donc être utilisé comme n'importe quel autre fournisseur de chat, et montre une fabrique qui retourne soit un OllamaApiClient, soit un OpenAIChatClient selon un argument de fournisseur. L'intérêt est de tester un modèle local et un modèle distant derrière la même abstraction. Le revers est qu'une abstraction commune ne peut exposer que ce que les fournisseurs ont en commun. Les paramètres propres à Ollama, comme le contrôle fin du chargement de modèle ou certains réglages de génération, restent accessibles via l'interface IOllamaApiClient, pas via IChatClient. Le README signale par ailleurs un moteur d'outils reposant sur des générateurs de source, documenté séparément. Cette approche évite la réflexion à l'exécution, mais elle impose une étape de génération dans le cycle de compilation.
Native AOT : ce qu'il faut accepter en échange
Le support Native AOT est présenté comme opt-in. Le README montre la contrainte : il faut déclarer un JsonSerializerContext partiel, annoté avec JsonSerializable sur les types personnalisés, puis passer ce contexte au constructeur via une méthode de fabrique statique qui prend l'Uri, le nom de modèle et le contexte. Autrement dit, la sérialisation par réflexion ne fonctionne pas dans ce scénario et vous devez énumérer vos types. Pour une application qui manipule beaucoup de DTO, cette liste devient une charge de maintenance : ajouter un type sans l'inscrire dans le contexte produit une erreur à l'exécution, pas à la compilation. C'est un compromis classique de l'AOT, mais il faut le mesurer avant de choisir ce mode.
Limites et alternatives
La première limite est structurelle : OllamaSharp est un client. Sans serveur Ollama joignable, aucune méthode ne fonctionne. Les appels réseau, la disponibilité du serveur et le chargement des modèles en mémoire restent hors de son périmètre. La deuxième concerne la version de l'API. Le README affirme couvrir chaque endpoint, mais la cadence de publication du dépôt, avec plusieurs versions rapprochées, suggère un suivi actif d'une cible mouvante. Une application figée sur une version ancienne du paquet peut se retrouver décalée par rapport à un serveur récent. La troisième touche l'historique de conversation, abordée plus haut : pas de troncature automatique documentée. Comme alternative, on peut interroger l'API Ollama directement avec HttpClient et System.Text.Json. La différence n'est pas mince : vous contrôlez alors exactement la forme des requêtes, vous ne dépendez d'aucune couche intermédiaire, et vous n'avez aucune mise à jour de paquet à suivre. En échange, vous réimplémentez le parsing du streaming, la gestion des statuts de pull et le suivi des messages. Pour un seul endpoint appelé de temps en temps, ce coût est faible. Pour une application qui utilise conversations, outils, embeddings et gestion de modèles, il devient rapidement supérieur au coût d'adoption de la bibliothèque.
Conclusion éditoriale
OllamaSharp convient aux équipes .NET qui ont déjà un serveur Ollama en fonctionnement et qui veulent éviter d'écrire leur propre client HTTP. Il ne convient pas à celles qui cherchent une inférence embarquée sans processus externe, ni un fournisseur unique abstrait sur plusieurs backends. Avant d'adopter, vérifier la version du serveur Ollama en face, le comportement du suivi d'historique du Chat sur les longues conversations, et la configuration nécessaire au Native AOT si vous publiez en AOT.
Notes de la communauté