.NET Core集成开源大模型:Nanbeige 4.1-3B API的C#调用范例

张开发
2026/4/12 17:26:48 15 分钟阅读

分享文章

.NET Core集成开源大模型:Nanbeige 4.1-3B API的C#调用范例
.NET Core集成开源大模型Nanbeige 4.1-3B API的C#调用范例最近在做一个内部知识库问答的小工具后端用的是.NET Core。团队想引入一个轻量级的AI模型来处理一些简单的文本生成和问答任务要求是能本地部署、成本可控并且要能方便地集成到现有的WebAPI项目里。找了一圈发现Nanbeige 4.1-3B这个开源模型挺符合需求。3B的参数量不算大对硬件要求相对友好而且提供了标准的HTTP API接口用起来应该不复杂。但网上的资料大多集中在Python上关于怎么在.NET环境里调用的例子很少。所以我就花时间研究了一下把整个集成过程走通了。今天这篇文章就是把我怎么在ASP.NET Core项目里用C#调用Nanbeige API的完整过程分享出来。如果你也在找类似的方案希望这个实际的代码范例能帮你省点时间。1. 项目准备与环境搭建在开始写代码之前得先把基础环境准备好。这里假设你已经有一个可以运行的Nanbeige 4.1-3B模型服务它提供了HTTP API供我们调用。1.1 创建ASP.NET Core WebAPI项目打开Visual Studio或者直接用.NET CLI创建一个新的WebAPI项目。我用的是.NET 8但.NET 6或7的步骤也差不多。dotnet new webapi -n NanbeigeIntegrationDemo cd NanbeigeIntegrationDemo创建好后项目的基本结构就出来了。我们主要会修改和添加的文件集中在Controllers和Services这两个目录。1.2 理解Nanbeige API的基本格式在动手写代码前先看看我们要调用的API长什么样。根据Nanbeige的文档完成一次文本生成请求大概需要以下几个关键信息端点地址比如http://localhost:8000/v1/chat/completions请求方法POST请求体一个JSON对象里面至少包含model模型名称、messages对话历史这些字段。响应体也是一个JSON对象我们关心的生成文本通常在choices[0].message.content这个路径下。知道这些我们就能定义出C#里对应的数据模型了。2. 核心数据模型与接口定义为了让代码更清晰、更好维护我习惯先定义好数据结构和接口。这步做完后面写具体实现和控制器的时候思路会顺畅很多。2.1 定义API请求与响应模型在项目里新建一个Models文件夹然后添加两个类分别对应API的请求和响应。首先是请求模型它描述了我们要发送给Nanbeige服务的数据结构// Models/NanbeigeChatRequest.cs namespace NanbeigeIntegrationDemo.Models; public class NanbeigeChatRequest { // 指定要使用的模型例如 nanbeige-4.1-3b public string Model { get; set; } string.Empty; // 对话消息列表通常包含用户问题和可能的系统指令 public ListChatMessage Messages { get; set; } new ListChatMessage(); // 控制生成文本的随机性值越高越随机 public float Temperature { get; set; } 0.7f; // 生成结果的最大token数 public int MaxTokens { get; set; } 512; } // 定义一个消息类代表对话中的一条记录 public class ChatMessage { // 角色如 user, assistant, system public string Role { get; set; } string.Empty; // 消息内容 public string Content { get; set; } string.Empty; }然后是响应模型用于解析Nanbeige服务返回给我们的结果// Models/NanbeigeChatResponse.cs namespace NanbeigeIntegrationDemo.Models; public class NanbeigeChatResponse { // 本次请求的唯一ID public string Id { get; set; } string.Empty; // 响应创建的时间戳 public long Created { get; set; } // 模型名称 public string Model { get; set; } string.Empty; // 生成的候选回复列表 public ListChatChoice Choices { get; set; } new ListChatChoice(); // 本次请求消耗的token使用情况 public TokenUsage Usage { get; set; } new TokenUsage(); } public class ChatChoice { // 在候选列表中的索引 public int Index { get; set; } // 生成的消息对象 public ChatMessage Message { get; set; } new ChatMessage(); // 结束原因如 stop 或 length public string FinishReason { get; set; } string.Empty; } public class TokenUsage { // 提示词消耗的token数 public int PromptTokens { get; set; } // 生成内容消耗的token数 public int CompletionTokens { get; set; } // 总token数 public int TotalTokens { get; set; } }2.2 定义服务接口接下来定义一个服务接口。这样做的好处是以后如果你想换一个AI服务提供商或者需要对HTTP调用进行单元测试会非常方便。在Services文件夹下创建INanbeigeAIService.cs。// Services/INanbeigeAIService.cs namespace NanbeigeIntegrationDemo.Services; public interface INanbeigeAIService { // 发送聊天请求并获取回复 Taskstring GetChatCompletionAsync(string userMessage, CancellationToken cancellationToken default); // 可选的流式响应方法如果API支持 // IAsyncEnumerablestring GetChatCompletionStreamAsync(string userMessage, CancellationToken cancellationToken default); }接口很简单核心就是一个异步方法输入用户的问题返回AI生成的答案。3. 实现HTTP调用服务接口定义好了现在来实现它。这里我们会用到.NET Core里最常用的HttpClient来发送HTTP请求。3.1 配置与依赖注入首先我们需要一个地方来管理API的基地址等配置。我选择使用.NET的IOptions模式。在appsettings.json里添加配置{ Logging: { LogLevel: { Default: Information, Microsoft.AspNetCore: Warning } }, NanbeigeSettings: { BaseUrl: http://localhost:8000/v1/, ModelName: nanbeige-4.1-3b, DefaultMaxTokens: 512, DefaultTemperature: 0.7 }, AllowedHosts: * }然后创建一个对应的配置类// Models/NanbeigeSettings.cs namespace NanbeigeIntegrationDemo.Models; public class NanbeigeSettings { public string BaseUrl { get; set; } string.Empty; public string ModelName { get; set; } string.Empty; public int DefaultMaxTokens { get; set; } 512; public float DefaultTemperature { get; set; } 0.7f; }3.2 核心服务实现现在来实现最关键的NanbeigeAIService。在Services文件夹下创建NanbeigeAIService.cs。// Services/NanbeigeAIService.cs using System.Text; using System.Text.Json; using Microsoft.Extensions.Options; using NanbeigeIntegrationDemo.Models; namespace NanbeigeIntegrationDemo.Services; public class NanbeigeAIService : INanbeigeAIService { private readonly HttpClient _httpClient; private readonly NanbeigeSettings _settings; private readonly ILoggerNanbeigeAIService _logger; private readonly JsonSerializerOptions _jsonOptions; // 通过构造函数注入HttpClient、配置和日志 public NanbeigeAIService( HttpClient httpClient, IOptionsNanbeigeSettings settings, ILoggerNanbeigeAIService logger) { _httpClient httpClient; _settings settings.Value; _logger logger; // 配置JSON序列化选项使用默认的驼峰命名策略 _jsonOptions new JsonSerializerOptions { PropertyNamingPolicy JsonNamingPolicy.CamelCase, WriteIndented false // 请求体不需要缩进节省空间 }; // 设置HttpClient的基础地址 if (!string.IsNullOrEmpty(_settings.BaseUrl)) { _httpClient.BaseAddress new Uri(_settings.BaseUrl); } } public async Taskstring GetChatCompletionAsync(string userMessage, CancellationToken cancellationToken default) { // 1. 构建请求模型 var request new NanbeigeChatRequest { Model _settings.ModelName, Messages new ListChatMessage { new ChatMessage { Role user, Content userMessage } }, MaxTokens _settings.DefaultMaxTokens, Temperature _settings.DefaultTemperature }; // 2. 序列化为JSON var jsonContent JsonSerializer.Serialize(request, _jsonOptions); using var httpContent new StringContent(jsonContent, Encoding.UTF8, application/json); // 3. 发送POST请求 _logger.LogInformation(Sending request to Nanbeige API. Message: {Message}, userMessage); HttpResponseMessage response; try { response await _httpClient.PostAsync(chat/completions, httpContent, cancellationToken); } catch (HttpRequestException ex) { _logger.LogError(ex, Failed to connect to Nanbeige API.); throw new Exception(无法连接到AI服务请检查服务是否运行。, ex); } // 4. 检查响应状态 if (!response.IsSuccessStatusCode) { var errorBody await response.Content.ReadAsStringAsync(cancellationToken); _logger.LogError(Nanbeige API returned error. Status: {StatusCode}, Body: {ErrorBody}, response.StatusCode, errorBody); throw new Exception($AI服务请求失败状态码: {(int)response.StatusCode}); } // 5. 读取并解析响应 var responseBody await response.Content.ReadAsStringAsync(cancellationToken); NanbeigeChatResponse? apiResponse; try { apiResponse JsonSerializer.DeserializeNanbeigeChatResponse(responseBody, _jsonOptions); } catch (JsonException ex) { _logger.LogError(ex, Failed to parse Nanbeige API response. Body: {ResponseBody}, responseBody); throw new Exception(解析AI服务响应失败。, ex); } // 6. 提取生成的文本 if (apiResponse?.Choices?.FirstOrDefault()?.Message?.Content is string content !string.IsNullOrWhiteSpace(content)) { _logger.LogInformation(Successfully received response from Nanbeige API.); return content.Trim(); } _logger.LogWarning(Nanbeige API response did not contain valid content. Response: {Response}, apiResponse); return 抱歉我暂时无法处理这个问题。; } }这段代码做了几件关键事情依赖注入通过构造函数拿到了配置好的HttpClient、NanbeigeSettings和ILogger。构建请求根据用户输入组装成API要求的JSON格式。发送请求使用HttpClient.PostAsync发送POST请求。错误处理对网络错误、HTTP错误状态码、JSON解析错误都做了捕获和日志记录。提取结果从响应的JSON中找到我们需要的文本内容。3.3 注册服务到依赖注入容器最后一步打开Program.cs文件把我们刚写的服务和配置注册进去。// Program.cs using NanbeigeIntegrationDemo.Services; using NanbeigeIntegrationDemo.Models; var builder WebApplication.CreateBuilder(args); // 添加服务到容器 builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 1. 配置NanbeigeSettings绑定到appsettings.json中的对应节点 builder.Services.ConfigureNanbeigeSettings( builder.Configuration.GetSection(NanbeigeSettings)); // 2. 注册一个命名的HttpClient专门用于调用Nanbeige API builder.Services.AddHttpClientINanbeigeAIService, NanbeigeAIService((serviceProvider, client) { // 基础地址在NanbeigeAIService的构造函数中设置这里可以配置一些客户端级别的默认值 client.Timeout TimeSpan.FromSeconds(60); // 设置超时时间 client.DefaultRequestHeaders.Add(Accept, application/json); }) .ConfigurePrimaryHttpMessageHandler(() new HttpClientHandler { // 根据你的部署环境可能需要调整SSL证书验证 ServerCertificateCustomValidationCallback (message, cert, chain, errors) true // 仅用于开发环境生产环境请谨慎 }); // 3. 注册我们的AI服务 builder.Services.AddScopedINanbeigeAIService, NanbeigeAIService(); var app builder.Build(); // 配置HTTP请求管道 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();这里用了AddHttpClientTService, TImplementation这个扩展方法它会帮我们管理HttpClient的生命周期并自动注入到NanbeigeAIService中这是目前推荐的做法。4. 构建智能对话控制器服务层准备好了现在来创建一个WebAPI控制器对外提供聊天接口。在Controllers文件夹下新建ChatController.cs。// Controllers/ChatController.cs using Microsoft.AspNetCore.Mvc; using NanbeigeIntegrationDemo.Services; namespace NanbeigeIntegrationDemo.Controllers; [ApiController] [Route(api/[controller])] public class ChatController : ControllerBase { private readonly INanbeigeAIService _aiService; private readonly ILoggerChatController _logger; public ChatController(INanbeigeAIService aiService, ILoggerChatController logger) { _aiService aiService; _logger logger; } // POST api/chat [HttpPost] public async TaskIActionResult PostChat([FromBody] ChatRequest request) { // 1. 验证输入 if (request null || string.IsNullOrWhiteSpace(request.Message)) { _logger.LogWarning(Received invalid chat request.); return BadRequest(new { error 请求无效请输入消息内容。 }); } _logger.LogInformation(Processing chat request: {Message}, request.Message); try { // 2. 调用AI服务 var responseText await _aiService.GetChatCompletionAsync(request.Message); // 3. 返回成功响应 var response new ChatResponse { Reply responseText, Timestamp DateTime.UtcNow }; return Ok(response); } catch (Exception ex) { // 4. 处理异常 _logger.LogError(ex, Error processing chat request.); // 可以根据异常类型返回更具体的错误信息 return StatusCode(500, new { error 处理您的请求时出现错误请稍后重试。 }); } } // 可选的添加一个简单的GET请求用于健康检查或测试 [HttpGet(test)] public IActionResult GetTest() { return Ok(new { status Chat API is running., timestamp DateTime.UtcNow }); } } // 简单的请求/响应模型用于控制器接口 public class ChatRequest { public string Message { get; set; } string.Empty; } public class ChatResponse { public string Reply { get; set; } string.Empty; public DateTime Timestamp { get; set; } }这个控制器做了几件事定义路由通过[Route(api/[controller])]属性它的访问地址会是/api/chat。依赖注入在构造函数中注入了我们之前写的INanbeigeAIService。处理POST请求PostChat方法接收一个包含用户消息的JSON调用AI服务然后返回AI的回复。输入验证与错误处理对空消息做了检查并对服务调用过程中的异常进行了捕获和日志记录。健康检查端点加了一个简单的/api/chat/testGET接口方便测试服务是否正常。5. 运行测试与效果展示代码都写完了现在来试试看效果怎么样。5.1 启动项目并测试接口首先确保你的Nanbeige模型服务已经在运行比如在http://localhost:8000。然后在项目根目录运行dotnet run项目启动后打开浏览器访问https://localhost:5001/swagger端口号可能不同注意看控制台输出你应该能看到Swagger UI页面里面列出了我们的ChatController的接口。点击POST /api/Chat点击“Try it out”然后在请求体里输入{ message: 用C#写一个Hello World程序 }点击“Execute”如果一切正常你会收到一个类似这样的响应{ reply: 以下是一个简单的C# Hello World程序\n\ncsharp\nusing System;\n\nclass Program\n{\n static void Main()\n {\n Console.WriteLine(\Hello, World!\);\n }\n}\n\n\n这段代码定义了一个Program类在Main方法中使用Console.WriteLine输出字符串。, timestamp: 2024-05-27T08:30:00Z }5.2 处理更复杂的对话场景上面的例子是单轮对话。如果你想支持多轮对话让AI记住上下文就需要稍微修改一下服务层。思路是在请求的Messages列表里不仅包含当前用户的问题还要包含之前的历史对话。你可以修改INanbeigeAIService接口和它的实现增加一个接收ListChatMessage的方法或者在你的业务逻辑层维护一个对话会话Session的概念每次请求时把历史记录也传进去。5.3 实际集成中的一些考虑在实际项目里集成时还有几个点可能需要你关注性能与超时模型推理可能需要几秒甚至更长时间要根据实际情况调整HttpClient的Timeout属性并在前端做好加载状态提示。错误重试对于网络波动等临时性错误可以考虑增加重试机制使用Polly这类库会很方便。API密钥与认证如果你的Nanbeige服务部署在公网并需要认证需要在HttpClient的DefaultRequestHeaders中添加相应的认证头如Authorization。日志与监控像代码里做的那样在关键步骤记录日志对于排查问题非常有帮助。6. 总结走完这一遍你会发现把Nanbeige这样的开源大模型集成到.NET Core项目里其实并没有想象中那么复杂。核心就是用好HttpClient处理HTTP请求用System.Text.Json处理JSON序列化再结合.NET Core强大的依赖注入体系把各部分清晰地组织起来。这种做法的好处是解耦得很好。ChatController不关心AI服务具体怎么实现的它只依赖一个INanbeigeAIService接口。哪天如果你想换另一个兼容OpenAI API格式的模型只需要换掉NanbeigeAIService的实现或者甚至通过配置动态选择不同的服务提供商控制器代码一行都不用改。代码里我尽量加了详细的注释和错误处理你可以直接拿去用或者根据自己项目的需求进行调整。比如加上流式响应如果API支持、对话历史管理、更复杂的提示词工程等等。希望这个具体的例子能帮你打开思路更快地在自己的.NET应用里用上AI能力。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章