前言

C#手写Ollama服务交互,实现本地模型对话

  • 最近使用C#调用OllamaSharpe库实现Ollama本地对话,然后思考着能否自己实现这个功能。
  • 经过一番查找,和查看OllamaSharpe源码发现确实可以。
  • 其实就是开启Ollama服务后,发送HTTP请求,获取返回结果以及一些数据处理。

基本流程

【C#】如何实现手写Ollama服务交互,实现本地模型对话。_Ollama

//创建请求体:模型名称、提示语、是否流式生成
        var request = new RequestModel{Model = model,Prompt = prompt,Stream = false};
        // 将请求体序列化为JSON
        var json = JsonSerializer.Serialize(request);
        // 创建HTTP请求内容
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        // 发送POST请求
        var response = await _httpClient.PostAsync("/api/generate", content);
        // 确保请求成功
        response.EnsureSuccessStatusCode();
        // 读取并返回响应内容
        string responseString = await response.Content.ReadAsStringAsync();
        ///解析相应字符串
        ResponseModel results = JsonSerializer.Deserialize<ResponseModel>(responseString);
        //返回结果
        return results.Response;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

项目结构

  • OllamaClient:实现基本的对话请求、获取模型列表功能。
  • Model :创建模型结果的一些参数。
  • RequestModel:请求参数模型。
  • ResponseModel:结果参数模型,用于解析返回的结果。
  • MainWindow:用户界面。
  • MainWindowViewModel:界面交互业务处理

【C#】如何实现手写Ollama服务交互,实现本地模型对话。_c#_02

案例

模型加载

【C#】如何实现手写Ollama服务交互,实现本地模型对话。_c#_03

发送聊天

【C#】如何实现手写Ollama服务交互,实现本地模型对话。_Ollama_04

代码

OllamaSharpe

Ollama客户端 OllamaClient
public class OllamaClient
    {
        public IEnumerable<Model> ModelList { get; set; }

        private readonly HttpClient _httpClient;
        public OllamaClient(string baseAddress = "http://localhost:11434")
        {
            _httpClient = new HttpClient
            {
                BaseAddress = new Uri(baseAddress)
            };
            ExecuteCommand("ollama list");  //启动Ollama服务
        }
        /// <summary>
        /// 异步生成文本
        /// </summary>
        public async Task<string> GenerateTextAsync(string model, string prompt)
        {
            try
            {
                //创建请求体:模型名称、提示语、是否流式生成
                var request = new RequestModel{Model = model,Prompt = prompt,Stream = false};
                // 将请求体序列化为JSON
                var json = JsonSerializer.Serialize(request);
                // 创建HTTP请求内容
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                // 发送POST请求
                var response = await _httpClient.PostAsync("/api/generate", content);
                // 确保请求成功
                response.EnsureSuccessStatusCode();
                // 读取并返回响应内容
                string responseString = await response.Content.ReadAsStringAsync();
                ///解析相应字符串
                ResponseModel results = JsonSerializer.Deserialize<ResponseModel>(responseString);
                //返回结果
                return results.Response;
            }
            catch (HttpRequestException e)
            {
                throw new Exception($"Request failed: {e.Message}");
            }
        }

        /// <summary>
        /// 异步流式生成文本
        /// </summary>
        public async IAsyncEnumerable<string> StreamGenerateTextAsync(string model, string prompt)
        {
            //创建请求体:模型名称、提示语、是否流式生成
            var request = new RequestModel{Model = model,Prompt = prompt, Stream = true};
            // 将请求体序列化为JSON
            var json = JsonSerializer.Serialize(request);
            //创建HTTP请求内容
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            //发送POST请求
            using var response = await _httpClient.PostAsync("/api/generate", content);
            // 确保请求成功
            response.EnsureSuccessStatusCode();
            // 读取流并解析为ResponseModel
            using var stream = await response.Content.ReadAsStreamAsync();
            // 创建流读取器
            using var reader = new StreamReader(stream);
            // 循环读取流
            while (!reader.EndOfStream)
            {