Spring_couplet_generation 模型服务化.NET Core Web API 集成案例春联生成听起来是个挺有意思的AI应用但怎么把它变成你.NET项目里一个能随时调用的服务呢很多.NET开发者可能都遇到过类似的问题看到一个不错的AI模型想把它集成到自己的系统里结果发现要么是Python写的要么部署起来很麻烦和自己的技术栈格格不入。今天咱们就来聊聊怎么用你最熟悉的.NET Core把那个能写春联的AI模型包装成一个干净利落的Web API。你不用去学Python也不用折腾复杂的部署脚本就用你平时写业务代码的那套方法把AI能力变成你项目里一个普通的服务。整个过程就像给你的项目加了个新功能模块一样自然。1. 项目准备与环境搭建首先咱们得把项目架子搭起来。这里假设你已经有一个部署好的春联生成服务它可能跑在某个服务器上提供了一个HTTP接口。你的任务就是在.NET Core里写个“中间人”去调用这个接口然后把结果整理好返回给前端。打开你的Visual Studio或者命令行创建一个新的ASP.NET Core Web API项目。用.NET 6或者.NET 8都行它们对这类任务支持得都很好。dotnet new webapi -n CoupletApiService cd CoupletApiService创建好项目后咱们需要安装几个必要的NuGet包。主要就是用来发HTTP请求的。!-- 在CoupletApiService.csproj文件中确保包含以下包引用 -- ItemGroup PackageReference IncludeMicrosoft.Extensions.Http Version8.0.0 / !-- 根据你的.NET版本选择合适版本 -- /ItemGroup接下来在appsettings.json文件里加上咱们要调用的那个AI服务的地址。别把地址硬编码在代码里用配置管理才是好习惯。{ Logging: { LogLevel: { Default: Information, Microsoft.AspNetCore: Warning } }, AllowedHosts: *, AiService: { BaseUrl: http://你的-ai服务-地址:端口, // 替换成你实际的服务地址 GenerateEndpoint: /generate, // 生成春联的端点路径 TimeoutSeconds: 30 // 请求超时时间 } }环境准备好了咱们就可以开始设计这个“中间人”服务怎么工作了。2. 核心服务层设计这个“中间人”在咱们项目里就是一个服务类。它的活很简单接收一个上联或者主题词去调用AI服务拿到生成的下联和横批然后打包好返回。我们先定义一下数据长什么样。在Models文件夹下创建几个类。// Models/GenerationRequest.cs namespace CoupletApiService.Models; public class GenerationRequest { /// summary /// 输入的上联或主题关键词例如“新春”或“江山如画” /// /summary public string InputText { get; set; } string.Empty; /// summary /// 可选参数例如生成风格、长度要求等 /// /summary public Dictionarystring, object? Parameters { get; set; } }// Models/CoupletResponse.cs namespace CoupletApiService.Models; public class CoupletResponse { /// summary /// 生成的上联可能与输入相同或由模型补全 /// /summary public string UpperLine { get; set; } string.Empty; /// summary /// 生成的下联 /// /summary public string LowerLine { get; set; } string.Empty; /// summary /// 生成的横批 /// /summary public string HorizontalScroll { get; set; } string.Empty; /// summary /// 生成耗时毫秒 /// /summary public long GenerationTimeMs { get; set; } /// summary /// 是否成功 /// /summary public bool Success { get; set; } /// summary /// 错误信息如果Success为false /// /summary public string? ErrorMessage { get; set; } }数据模型定义好了接下来就是干活的服务类。我们在Services文件夹下创建ICoupletService接口和它的实现。// Services/ICoupletService.cs using CoupletApiService.Models; namespace CoupletApiService.Services; public interface ICoupletService { TaskCoupletResponse GenerateCoupletAsync(GenerationRequest request, CancellationToken cancellationToken default); }// Services/CoupletService.cs using System.Text; using System.Text.Json; using CoupletApiService.Models; using Microsoft.Extensions.Options; namespace CoupletApiService.Services; public class CoupletService : ICoupletService { private readonly HttpClient _httpClient; private readonly AiServiceSettings _settings; private readonly ILoggerCoupletService _logger; public CoupletService(HttpClient httpClient, IOptionsAiServiceSettings settings, ILoggerCoupletService logger) { _httpClient httpClient; _settings settings.Value; _logger logger; } public async TaskCoupletResponse GenerateCoupletAsync(GenerationRequest request, CancellationToken cancellationToken default) { var stopwatch System.Diagnostics.Stopwatch.StartNew(); var response new CoupletResponse(); try { // 1. 准备请求数据 var requestData new { prompt request.InputText, parameters request.Parameters }; var jsonContent JsonSerializer.Serialize(requestData); var httpContent new StringContent(jsonContent, Encoding.UTF8, application/json); // 2. 发送请求到AI服务 var url ${_settings.BaseUrl.TrimEnd(/)}/{_settings.GenerateEndpoint.TrimStart(/)}; _logger.LogInformation(正在调用AI服务: {Url}, url); var httpResponse await _httpClient.PostAsync(url, httpContent, cancellationToken); // 3. 处理响应 if (httpResponse.IsSuccessStatusCode) { var responseJson await httpResponse.Content.ReadAsStringAsync(cancellationToken); // 这里需要根据你实际AI服务返回的JSON结构来解析 // 假设返回格式为{ upper_line: ..., lower_line: ..., horizontal_scroll: ... } using var doc JsonDocument.Parse(responseJson); var root doc.RootElement; response.UpperLine root.GetProperty(upper_line).GetString() ?? request.InputText; response.LowerLine root.GetProperty(lower_line).GetString() ?? string.Empty; response.HorizontalScroll root.GetProperty(horizontal_scroll).GetString() ?? string.Empty; response.Success true; } else { var errorContent await httpResponse.Content.ReadAsStringAsync(cancellationToken); _logger.LogError(AI服务调用失败。状态码: {StatusCode}, 响应: {ErrorContent}, httpResponse.StatusCode, errorContent); response.Success false; response.ErrorMessage $AI服务返回错误: {httpResponse.StatusCode}; } } catch (HttpRequestException ex) { _logger.LogError(ex, 调用AI服务时发生网络错误); response.Success false; response.ErrorMessage $网络请求失败: {ex.Message}; } catch (JsonException ex) { _logger.LogError(ex, 解析AI服务响应时发生JSON错误); response.Success false; response.ErrorMessage 响应数据格式错误; } catch (Exception ex) { _logger.LogError(ex, 生成春联时发生未知错误); response.Success false; response.ErrorMessage 内部服务错误; } finally { stopwatch.Stop(); response.GenerationTimeMs stopwatch.ElapsedMilliseconds; _logger.LogInformation(春联生成完成耗时: {ElapsedMs}ms, 成功: {Success}, response.GenerationTimeMs, response.Success); } return response; } }你可能注意到了上面用到了一个AiServiceSettings类。我们需要在Models文件夹下创建它用来映射配置文件里的设置。// Models/AiServiceSettings.cs namespace CoupletApiService.Models; public class AiServiceSettings { public string BaseUrl { get; set; } string.Empty; public string GenerateEndpoint { get; set; } string.Empty; public int TimeoutSeconds { get; set; } 30; }服务类的核心代码就这些。它做了几件事配置HTTP客户端、序列化请求、发送请求、处理响应和异常。这些都是.NET Core里做HTTP集成的标准操作。3. 依赖注入与配置管理写好了服务类怎么让它能在项目里用起来呢这就轮到.NET Core的依赖注入容器上场了。我们打开Program.cs文件把服务配置进去。// Program.cs using CoupletApiService.Models; using CoupletApiService.Services; var builder WebApplication.CreateBuilder(args); // 添加服务到容器 builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 1. 配置AiServiceSettings builder.Services.ConfigureAiServiceSettings( builder.Configuration.GetSection(AiService)); // 2. 注册HttpClient并配置超时和基地址 builder.Services.AddHttpClientICoupletService, CoupletService((serviceProvider, client) { var settings serviceProvider.GetRequiredServiceIOptionsAiServiceSettings().Value; client.BaseAddress new Uri(settings.BaseUrl); client.Timeout TimeSpan.FromSeconds(settings.TimeoutSeconds); // 可以在这里添加默认请求头如认证信息等 // client.DefaultRequestHeaders.Add(Authorization, Bearer your-token); }) .ConfigurePrimaryHttpMessageHandler(() new HttpClientHandler { // 根据实际情况配置例如是否忽略SSL证书验证仅限开发环境 ServerCertificateCustomValidationCallback (message, cert, chain, errors) { // 生产环境应进行严格验证 // 这里仅为示例开发环境可临时忽略 return true; } }); // 3. 注册业务服务 builder.Services.AddScopedICoupletService, CoupletService(); var app builder.Build(); // 配置HTTP请求管道 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();这段配置代码做了三件关键事第一把appsettings.json里的配置绑定到AiServiceSettings类第二注册了一个专用于CoupletService的HttpClient并设置了基础地址和超时第三把CoupletService本身注册为作用域服务。用依赖注入的好处很明显配置集中管理、HttpClient的生命周期由框架管理避免了端口耗尽问题、服务易于测试和替换。4. 控制器设计与API暴露服务准备好了现在需要提供一个HTTP端点给外部调用。我们在Controllers文件夹下创建一个控制器。// Controllers/CoupletController.cs using CoupletApiService.Models; using CoupletApiService.Services; using Microsoft.AspNetCore.Mvc; namespace CoupletApiService.Controllers; [ApiController] [Route(api/[controller])] public class CoupletController : ControllerBase { private readonly ICoupletService _coupletService; private readonly ILoggerCoupletController _logger; public CoupletController(ICoupletService coupletService, ILoggerCoupletController logger) { _coupletService coupletService; _logger logger; } [HttpPost(generate)] [ProducesResponseType(typeof(CoupletResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async TaskActionResultCoupletResponse GenerateCouplet([FromBody] GenerationRequest request) { if (string.IsNullOrWhiteSpace(request.InputText)) { return BadRequest(new ProblemDetails { Title 无效请求, Detail InputText不能为空, Status StatusCodes.Status400BadRequest }); } _logger.LogInformation(收到春联生成请求输入: {InputText}, request.InputText); try { var response await _coupletService.GenerateCoupletAsync(request); if (response.Success) { _logger.LogInformation(春联生成成功。上联: {UpperLine}, 下联: {LowerLine}, response.UpperLine, response.LowerLine); return Ok(response); } else { // AI服务本身处理失败返回502错误表示网关错误 _logger.LogWarning(春联生成失败: {ErrorMessage}, response.ErrorMessage); return StatusCode(StatusCodes.Status502BadGateway, new ProblemDetails { Title AI服务错误, Detail response.ErrorMessage, Status StatusCodes.Status502BadGateway }); } } catch (TaskCanceledException) { _logger.LogWarning(春联生成请求超时或被取消); return StatusCode(StatusCodes.Status504GatewayTimeout, new ProblemDetails { Title 请求超时, Detail 调用AI服务超时请稍后重试, Status StatusCodes.Status504GatewayTimeout }); } catch (Exception ex) { _logger.LogError(ex, 处理春联生成请求时发生未预期错误); return StatusCode(StatusCodes.Status500InternalServerError, new ProblemDetails { Title 内部服务器错误, Detail 处理请求时发生错误, Status StatusCodes.Status500InternalServerError }); } } // 可选添加一个简单的健康检查端点 [HttpGet(health)] public IActionResult HealthCheck() { return Ok(new { status healthy, timestamp DateTime.UtcNow }); } }这个控制器虽然代码不多但考虑得比较周全。它定义了一个POST /api/couplet/generate的端点接收JSON格式的请求体。里面做了输入验证、日志记录、调用服务、以及根据服务返回的结果或异常返回不同的HTTP状态码和标准的ProblemDetails响应。这样前端调用方就能清晰地知道请求成功还是失败以及失败的原因是什么。5. 运行测试与效果验证代码都写完了咱们来试试看效果怎么样。在项目根目录运行dotnet run或者直接用Visual Studio按F5启动。项目启动后打开浏览器访问https://localhost:端口/swagger如果启用了Swagger你应该能看到自动生成的API文档。现在咱们用Postman或者curl来测试一下。假设你的AI服务接收一个简单的JSON比如{“prompt”: “新春”}然后返回春联。# 示例curl命令 curl -X POST https://localhost:端口/api/couplet/generate \ -H Content-Type: application/json \ -d {inputText:新春}如果一切正常你会收到一个类似这样的JSON响应{ upperLine: 新春, lowerLine: 佳节, horizontalScroll: 吉祥如意, generationTimeMs: 450, success: true, errorMessage: null }当然实际的下联和横批内容取决于你的AI模型。如果AI服务挂了或者网络不通你会收到一个502错误告诉你网关错误。如果请求格式不对你会收到400错误。在实际项目里你可能还需要考虑更多东西比如给AI服务的调用加上重试机制用Polly库很容易实现或者加个缓存对相同的输入直接返回缓存结果不用每次都调AI服务。还可以加个限流防止被刷接口。这些都是在生产环境里提升稳定性和性能的常见做法。6. 总结走完这一趟你会发现用.NET Core集成一个AI服务其实和你平时调用任何一个第三方HTTP API没什么本质区别。核心就是用好HttpClient配合依赖注入来管理配置和生命周期然后在控制器里做好错误处理和日志记录。这种做法的好处是你的业务代码和具体的AI模型实现完全解耦了。哪天你想换一个更好的春联生成模型或者这个AI服务升级了接口你只需要调整CoupletService里发送请求和解析响应的那部分代码控制器和前端完全不用动。整个集成过程很自然地融入了.NET Core的开发模式对于已经熟悉这套技术的团队来说学习和维护成本都很低。如果你正在做类似的项目不妨按这个思路试试。先从最简单的版本跑通然后再根据实际需求慢慢加上重试、缓存、监控这些功能。这样一步步来既能快速看到效果又能保证代码的质量和可维护性。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。