与Ollama服务通信支持以下三种方式1. cURL (命令行工具)详细说明cURL是一个利用URL语法在命令行下工作的文件传输工具。它是与Ollama交互最原始、最直接的方式相当于手动构造并发送HTTP请求。你需要在终端命令提示符中逐条输入命令并观察返回的原始JSON数据。主要特点无需安装大多数操作系统Windows 10/11、macOS、Linux都预装了cURL。完全控制你可以精确控制请求头Header和请求体Body的每一个字段。即时反馈适合快速测试API接口是否工作正常查看原始响应结构。缺点手动处理复杂的JSON和流式响应比较繁琐不适合构建大型应用。详细使用示例场景1测试服务是否可用列出已安装的模型curl http://localhost:11434/api/tags返回示例你会看到一个JSON数组列出了所有已下载的模型名称、大小、修改时间等信息。用途确认Ollama服务已启动并查看可用的模型名称需要完整名称如qwen3:4b。场景2使用/api/generate端点进行单次文本生成这个端点适合简单的问答或文本补全任务。curl http://localhost:11434/api/generate -d { model: qwen3:4b, prompt: 请用中文简单介绍一下人工智能。, stream: false }参数解释-d指定要发送的JSON数据。model必须使用ollama list中显示的完整模型名称。prompt你的提问内容。stream: false设置为false表示等待完整响应后一次性返回若为true则会以Server-Sent EventsSSE流式返回数据块。返回示例一个包含model、created_at、response生成的文本、done是否完成等字段的JSON对象。场景3使用/api/chat端点进行对话支持多轮消息/api/chat端点的结构更清晰适合构建聊天机器人。curl http://localhost:11434/api/chat -d { model: gemma3:4b, messages: [ {role: user, content: 你好请介绍一下你自己。} ], stream: false }参数解释messages是一个消息数组可以包含system系统设定、user用户和assistant助手角色的消息实现上下文对话。返回示例响应中的message字段包含了助手的回复内容。2. Python 库 (ollama)详细说明这是Ollama官方提供的Python SDK它将底层的HTTP请求封装成了直观的Python函数。你不需要关心URL、JSON序列化或状态码库会帮你处理这些细节。主要特点高级封装代码简洁符合Python风格易于学习和使用。自动管理自动处理JSON的序列化与反序列化异常会以Python异常的形式抛出。流式支持通过简单的参数控制如streamTrue即可实现流式响应并迭代处理每个数据块。生态集成可以无缝集成到现有的Python AI项目如数据分析、机器学习流水线中。详细使用示例第一步安装库pip install ollama第二步编写Python代码场景1最简单的同步调用使用/api/chatimport ollama # 调用chat接口发送一条用户消息 response ollama.chat( modelqwen3:4b, # 指定模型 messages[{role: user, content: 为什么天空是蓝色的}] ) # 直接打印助手的回复内容 print(response[message][content])场景2实现流式响应逐字输出这对于提升用户体验非常重要可以让你像在使用ChatGPT一样看到文字逐个生成。import ollama # 启用流式输出 stream ollama.chat( modelgemma3:4b, messages[{role: user, content: 写一首关于夏天的短诗。}], streamTrue # 关键参数 ) # 迭代处理每一个响应块 for chunk in stream: # 每个chunk包含一个message字段其中content是本次新生成的部分文本 print(chunk[message][content], end, flushTrue) # 输出完成后换行 print()场景3维护多轮对话上下文通过不断向messages列表中添加历史记录模型就能“记住”之前的对话。import ollama # 初始化对话历史 messages [{role: system, content: 你是一位知识渊博的历史老师。}] while True: user_input input(你: ) if user_input.lower() exit: break # 将用户输入添加到历史中 messages.append({role: user, content: user_input}) # 发送完整历史获取回复 response ollama.chat(modelqwen3:4b, messagesmessages) assistant_reply response[message][content] # 将助手的回复也添加到历史中以便下一轮使用 messages.append({role: assistant, content: assistant_reply}) print(f助手: {assistant_reply})3. JavaScript/Node.js 库 (ollama)详细说明这是Ollama官方的JavaScript SDK支持在浏览器和Node.js环境中使用。它基于现代的async/await异步编程模型非常适合构建响应式的Web应用。主要特点全栈支持一套API既可以运行在前端浏览器中也可以运行在后端Node.js服务器上。Promise风格完美融入现代JavaScript异步流程可以使用async/await或.then()。类型安全如果使用TypeScript可以获得完整的类型提示减少错误。易于集成可以很方便地与React、Vue、Next.js等前端框架结合。详细使用示例第一步安装库在项目目录下初始化npm并安装npm init -y npm install ollama第二步编写Node.js代码场景1基本调用使用/api/chat创建一个index.js文件jimport { Ollama } from ollama; // 创建Ollama客户端实例可指定主机地址 const ollama new Ollama({ host: http://localhost:11434 }); async function basicChat() { try { // 发送聊天请求 const response await ollama.chat({ model: gemma3:4b, messages: [{ role: user, content: Node.js和Python有什么区别 }] }); // 打印助手的回复 console.log(response.message.content); } catch (error) { console.error(调用失败:, error); } } basicChat();使用命令运行node index.js场景2实现流式响应实时显示通过监听async迭代器可以逐块接收并处理响应例如在Web页面中动态更新UI。javascript复制下载import { Ollama } from ollama; const ollama new Ollama({ host: http://localhost:11434 }); async function streamChat() { // 发起流式请求 const streamResponse await ollama.chat({ model: qwen3:4b, messages: [{ role: user, content: 用JavaScript实现一个冒泡排序。 }], stream: true // 启用流式 }); // 遍历异步迭代器获取每个数据块 for await (const part of streamResponse) { // part.message.content 包含本次新生成的文本片段 process.stdout.write(part.message.content); // 在控制台连续输出 } console.log(); // 最终换行 } streamChat();场景3在浏览器中使用首先通过script typeimportmap或打包工具如Vite引入库。然后在浏览器JavaScript中用法与Node.js几乎完全相同这使得前后端可以共享逻辑。html!DOCTYPE html html head titleOllama 浏览器聊天/title /head body button idchatBtn问AI/button div idoutput/div script typeimportmap { imports: { ollama: https://cdn.jsdelivr.net/npm/ollama0.5.0/esm } } /script script typemodule import { Ollama } from ollama; const ollama new Ollama({ host: http://localhost:11434 }); document.getElementById(chatBtn).onclick async () { const output document.getElementById(output); output.innerText 思考中...; const response await ollama.chat({ model: gemma3:4b, messages: [{ role: user, content: 推荐一本适合初学者的编程书。 }] }); output.innerText response.message.content; }; /script /body /html总结与选择建议方式核心操作代码量适合场景优点缺点cURL手动拼接JSON在终端执行最少单条命令测试API、调试、快速验证直接、无需环境配置难以处理复杂逻辑不可用于生产Python库调用ollama.chat()函数很少后端服务、数据分析、脚本高级封装、生态丰富、易于调试仅限Python环境JavaScript库调用ollama.chat()异步方法很少Web前端、Node.js后端、全栈应用异步高性能、前后端通用需要对JavaScript异步编程有基本了解下面用C#实现聊天程序下面提供一个功能完整的C#控制台程序。它基于你提供的文章代码进行了重构和增强支持从多个本地模型中自由选择并优化了响应处理。主要改进点可用的模型列表动态获取并让你选择qwen3:4b或gemma3:4b如果本地已拉取。正确的API调用使用/api/chat端点更适合多轮对话并正确处理流式stream: false响应。清晰的实体类定义了与API响应匹配的ChatResponse类方便解析。友好的交互界面支持连续对话上下文未维护仅作演示和输入exit退出。1. 创建实体类 (用于解析JSON响应)在项目中新建一个ChatResponse.cs文件using System; using System.Text.Json.Serialization; namespace OllamaChat { // 对应 /api/chat 端点的响应格式 public class ChatResponse { [JsonPropertyName(model)] public string? Model { get; set; } [JsonPropertyName(created_at)] public DateTime CreatedAt { get; set; } [JsonPropertyName(message)] public Message? Message { get; set; } [JsonPropertyName(done)] public bool Done { get; set; } } public class Message { [JsonPropertyName(role)] public string? Role { get; set; } [JsonPropertyName(content)] public string? Content { get; set; } } }2. 主程序代码 (Program.cs)将以下代码替换到你的Program.cs中using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace OllamaChat { class Program { // 定义可用的模型列表请确保这些模型已通过 ollama pull 下载到本地 private static readonly Liststring AvailableModels new Liststring { qwen3:4b, gemma3:4b // 如果你有其他模型可以在这里添加例如 llama3.2:3b }; static async Task Main(string[] args) { Console.OutputEncoding Encoding.UTF8; // 支持中文显示 // 1. 检查Ollama服务是否可用 using var client new HttpClient(); client.Timeout TimeSpan.FromSeconds(120); // 推理可能需要较长时间 try { var healthCheck await client.GetAsync(http://localhost:11434/api/tags); if (!healthCheck.IsSuccessStatusCode) { Console.WriteLine(错误无法连接到Ollama服务。请确保Ollama正在运行。); Console.WriteLine(请启动Ollama应用程序或运行 ollama serve 命令。); return; } } catch { Console.WriteLine(错误无法连接到Ollama服务。请确保Ollama正在运行。); return; } // 2. 选择模型 Console.WriteLine( Ollama C# 聊天程序 ); Console.WriteLine(检测到的本地模型); for (int i 0; i AvailableModels.Count; i) { Console.WriteLine(${i 1}. {AvailableModels[i]}); } Console.Write(请选择模型的序号 (默认为1): ); string? inputChoice Console.ReadLine(); if (!int.TryParse(inputChoice, out int choice) || choice 1 || choice AvailableModels.Count) { choice 1; // 默认选择第一个 } string selectedModel AvailableModels[choice - 1]; Console.WriteLine($你选择了模型: {selectedModel}\n); // 3. 开始聊天循环 Console.WriteLine(输入你的问题输入 exit 退出程序。\n); while (true) { Console.Write(你: ); string? userInput Console.ReadLine(); if (string.IsNullOrEmpty(userInput)) continue; if (userInput.Trim().ToLower() exit) break; // 调用Ollama API await SendChatRequestAsync(client, selectedModel, userInput); Console.WriteLine(); // 输出后换行 } } private static async Task SendChatRequestAsync(HttpClient client, string model, string prompt) { try { // 构造请求体使用 /api/chat 端点 var requestBody new { model model, messages new[] { new { role user, content prompt } }, stream false // 设置为false以一次性获取完整响应 }; string json JsonSerializer.Serialize(requestBody); var content new StringContent(json, Encoding.UTF8, application/json); // 发送POST请求 HttpResponseMessage response await client.PostAsync( http://localhost:11434/api/chat, content ); if (response.IsSuccessStatusCode) { // 解析JSON响应 string responseJson await response.Content.ReadAsStringAsync(); var chatResponse JsonSerializer.DeserializeChatResponse(responseJson); if (chatResponse?.Message?.Content ! null) { Console.WriteLine($\n{model}: {chatResponse.Message.Content}); } else { Console.WriteLine(\n助手: (收到空响应)); } } else { string errorContent await response.Content.ReadAsStringAsync(); Console.WriteLine($\n请求失败 (HTTP {response.StatusCode}): {errorContent}); } } catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) { Console.WriteLine(\n错误: 请求超时模型推理时间过长。); } catch (Exception ex) { Console.WriteLine($\n发生异常: {ex.Message}); } } } }3. 运行与使用步骤确保环境已在本地安装Ollama。已通过命令行拉取了模型例如ollama pull qwen3:4b ollama pull gemma3:4bOllama服务正在运行可以在系统托盘中看到羊驼图标或通过ollama serve启动。创建项目在Visual Studio或VS Code中新建一个控制台应用.NET Core/.NET 5。添加代码将上述两个代码文件添加到项目中。运行按F5或dotnet run启动程序。根据提示选择模型然后开始聊天。这个程序为你提供了一个稳定、可直接运行的起点。你可以基于它进一步扩展比如添加多轮对话的上下文记忆功能、实现流式输出等。希望这能帮助你顺利开始Ollama的C#开发如果有其他问题随时可以提出。C#程序改进版增加了流式应当不用一次性输出更加人性化。using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace OllamaChat { class Program { private static readonly Liststring AvailableModels new Liststring { qwen3:4b, gemma3:4b }; private static bool _showThinking true; static async Task Main(string[] args) { Console.OutputEncoding Encoding.UTF8; // 检查服务 using var client new HttpClient(); client.Timeout TimeSpan.FromSeconds(180); try { var healthCheck await client.GetAsync(http://localhost:11434/api/tags); if (!healthCheck.IsSuccessStatusCode) { Console.WriteLine(错误无法连接到Ollama服务。); return; } Console.WriteLine(✅ Ollama 服务连接正常\n); } catch { Console.WriteLine(错误无法连接到Ollama服务。); return; } // 选择模型 Console.WriteLine( Ollama C# 流式聊天程序 ); for (int i 0; i AvailableModels.Count; i) { Console.WriteLine(${i 1}. {AvailableModels[i]}); } Console.Write(请选择模型的序号 (默认为1): ); string? inputChoice Console.ReadLine(); if (!int.TryParse(inputChoice, out int choice) || choice 1 || choice AvailableModels.Count) { choice 1; } string selectedModel AvailableModels[choice - 1]; Console.WriteLine($你选择了模型: {selectedModel}\n); Console.Write(是否显示思考过程(y/n, 默认为y): ); string? showInput Console.ReadLine(); _showThinking string.IsNullOrEmpty(showInput) || showInput.ToLower() ! n; Console.WriteLine(\n输入你的问题输入 exit 退出程序。\n); while (true) { Console.Write(你: ); string? userInput Console.ReadLine(); if (string.IsNullOrEmpty(userInput)) continue; if (userInput.Trim().ToLower() exit) break; await StreamChatAsync(client, selectedModel, userInput); Console.WriteLine(\n); } } private static async Task StreamChatAsync(HttpClient client, string model, string prompt) { try { var requestBody new { model model, prompt prompt, stream true }; string json JsonSerializer.Serialize(requestBody); var content new StringContent(json, Encoding.UTF8, application/json); using var request new HttpRequestMessage(HttpMethod.Post, http://localhost:11434/api/generate) { Content content }; using var response await client.SendAsync( request, HttpCompletionOption.ResponseHeadersRead ); if (!response.IsSuccessStatusCode) { string errorContent await response.Content.ReadAsStringAsync(); Console.WriteLine($\n请求失败 (HTTP {response.StatusCode}): {errorContent}); return; } using var stream await response.Content.ReadAsStreamAsync(); using var reader new System.IO.StreamReader(stream, Encoding.UTF8); string? line; bool hasContent false; int chunkCount 0; int tokenCount 0; // ✅ 状态管理 bool isThinkingPhase true; // 当前是否在思考阶段 bool thinkingStarted false; bool responseStarted false; // ✅ 先显示模型名称 Console.Write(${model}: ); while ((line await reader.ReadLineAsync()) ! null) { if (string.IsNullOrEmpty(line)) continue; try { using var doc JsonDocument.Parse(line); var root doc.RootElement; // ✅ 处理思考过程先显示 if (root.TryGetProperty(thinking, out var thinkingElement)) { string thinkingChunk thinkingElement.GetString() ?? ; if (!string.IsNullOrEmpty(thinkingChunk) _showThinking) { // 第一次出现思考时显示 思考中...\n if (!thinkingStarted) { Console.ForegroundColor ConsoleColor.DarkGray; Console.Write(思考中...\n); thinkingStarted true; } // ✅ 逐字输出思考内容 Console.Write(thinkingChunk); } } // ✅ 处理回答内容在思考之后 if (root.TryGetProperty(response, out var responseElement)) { string chunk responseElement.GetString() ?? ; if (!string.IsNullOrEmpty(chunk)) { // 如果还在思考阶段切换到回答阶段 if (isThinkingPhase thinkingStarted _showThinking) { Console.ResetColor(); Console.Write(\n\n); // 思考完成后换行 isThinkingPhase false; } else if (isThinkingPhase !thinkingStarted) { // 没有思考过程直接输出回答 isThinkingPhase false; } // ✅ 逐字输出回答 Console.Write(chunk); hasContent true; chunkCount; } } // ✅ 检查是否完成 if (root.TryGetProperty(done, out var doneElement) doneElement.GetBoolean()) { if (root.TryGetProperty(eval_count, out var evalCount)) { tokenCount evalCount.GetInt32(); } // ✅ 如果思考过程结束时没有换行补充换行 if (thinkingStarted _showThinking !isThinkingPhase) { // 已经换行了 } else if (thinkingStarted _showThinking isThinkingPhase) { // 思考结束但没有回答异常情况 Console.ResetColor(); } Console.WriteLine($\n\n[生成完成共 {tokenCount} 个 token{chunkCount} 个数据块]); break; } } catch (JsonException) { // 忽略无法解析的行 } } if (!hasContent) { Console.WriteLine((收到空响应)); } } catch (Exception ex) { Console.WriteLine($\n发生异常: {ex.Message}); } } } }