ASP.NET Core开发Chatbot API

在这里插入图片描述

本文介绍基于ASP.NET Core的Chatbot Restful API开发,通过调用大语言模型的SDK,完成一个简单的示例。并且通过容器化进行部署.

安装

首先需要安装.NET环境,笔者在Ubuntu 22.04通过二进制包进行安装,Windows和Mac下都有installer可以用. 选择的版本是.NET 8.

技术栈

我们分析一下要用到的技术栈,想要达到一个基本的demo需求,需要实现API,以及数据的查询存储,以及快速搭建运行环境.
因此我们选择postgresql存储数据,docker容器化实现快速部署. LLM服务选用了OpenAI.

Solution

首先创建一个solution,可以使用如下命令,或者使用IDE.

dotnet new sln

然后新建webapi工程并添加到solution中

mkdir WebApi
cd WebApi
dotnet new webapi
cd ..
dotnet sln add WebApi

完成创建后可以尝试restore并且简单build一下确认环境是否正常

dotnet restore
dotnet build

创建控制器

新建的webapi工程默认给了一个Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

这个代码模板已经实现了一个简单的API,但不是我们需要的基于controller的模式,为了使用controller,我们还要安装一些依赖包.

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet tool uninstall -g dotnet-aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool update -g dotnet-aspnet-codegenerator

Microsoft官方tutorial中给出的是:

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet tool uninstall -g dotnet-aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool update -g dotnet-aspnet-codegenerator

因为我们不使用EntityFrameworkCore,所以去掉了关于EntityFrameworkCore的引用.

然后是创建controller,例如我们命名为ChatController:

dotnet aspnet-codegenerator controller -name ChatController -api -outDir Controllers

创建后,我们可以得到ChatController.cs文件,稍作修改如下

using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ChatController(IChatService chatService) : ControllerBase
{
    [HttpPost]
    [Route("[action]")]
    public ActionResult<ChatResponse> Completions([FromBody] ChatRequest request)
    {
        var input = request.Text;
        var result = chatService.Complete(request);
        return Ok(result);
    }
}

这时,如果我们直接运行工程,会发现在swagger的页面中,找不到刚才添加的Chat endpoint,因为还需要一些配置
Program.cs中,我们需要让服务映射我们新增的controller.

builder.Services.AddControllers();
app.MapControllers();

上面是两行需要增加的代码,使整个Program.cs看起来这样

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapControllers();

//entry point
app.Run();

这时,再运行就会发现swagger中已经有相关的endpoint。

OpenAI SDK

使用OpenAI SDK非常简单,直接安装依赖包

dotnet add package OpenAI-DotNet --version 8.3.0

准备好一个Open AI的key,配置到环境变量中,创建一个Factory获取ChatClient(这是和OpenAI交互的客户端). 笔者使用的模型是gpt-3.5-turbo,单纯是实惠,lol.

public abstract class OpenAiClientFactory
{
    public static ChatClient Create()
    {
        var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
                     ?? throw new InvalidOperationException("OpenAI API key not set");
        return new ChatClient("gpt-3.5-turbo", apiKey);
    }
}

有了ChatClient后,就可以进行交互了. 这里涉及到的知识有AI对话点角色问题,涉及到3个角色:

  1. system
  2. assistant
  3. user

相关的概念可以查看文档.
进行一次AI对话就很方便了,直接调用complete方法即可

var prompt = $"""
                      You are an NLU expert help to do intent recognition, slot filling work. Now you are going to understand user input then give a proper result.
                      """;
var systemChatMessage = new SystemChatMessage(prompt);
var userChatMessage = new UserChatMessage(input);
var response = chatClient.CompleteChat([systemChatMessage, userChatMessage]);

这是一个模板代码,可以按照自己的需求修改.

容器化

为了快速运行,可以在项目中增加一个Dockrfile

FROM mcr.microsoft.com/dotnet/sdk:8.0

EXPOSE 5114

COPY . /app

WORKDIR /app

RUN dotnet restore && dotnet build

CMD [ "dotnet","run","--project","./WebApi" ]

通过docker快速打包后就能在所有支持docker的平台上快速演示demo.
在容器化方面,我们还可以使用docker compose来把数据库也和主程序一起启动。

Docker Compose 是 Docker 官方编排工具,用于定义和运行多容器 Docker 应用程序。使用 Docker Compose,你可以通过一个 YAML 文件来配置你的应用服务,然后使用一个简单的命令来启动和停止所有服务。

Docker Compose 的主要特点包括:

  1. 多容器编排:可以定义多个容器服务,并管理它们之间的依赖关系。

  2. 服务隔离:每个服务运行在独立的容器中,可以单独配置环境变量、卷挂载、网络等。

  3. 一键部署:通过 docker-compose up 命令,可以一次性启动配置文件中定义的所有服务。

  4. 版本控制:Docker Compose 文件(通常是 docker-compose.yml)可以被版本控制系统跟踪,方便团队协作和持续集成。

  5. 环境一致性:在开发、测试和生产环境中使用相同的配置文件,确保环境一致性。

  6. 网络管理:可以定义服务之间的网络连接,使得服务之间可以通过服务名进行通信。

  7. 数据卷管理:可以定义数据卷,实现数据的持久化和共享。

  8. 扩展性:支持通过环境变量和扩展文件来扩展配置。

  9. 命令行工具:提供了丰富的命令行工具,用于管理服务的生命周期,如启动、停止、重建、日志查看等。

一个基本的 docker-compose.yml 文件示例如下:

version: '3'
services:
  web:
    image: "nginx:latest"
    ports:
      - "80:80"
    volumes:
      - "/var/www:/usr/share/nginx/html"
    depends_on:
      - db
  db:
    image: "postgres:latest"
    environment:
      POSTGRES_DB: "mydb"
      POSTGRES_USER: "user"
      POSTGRES_PASSWORD: "password"

在我们的例子中,还需要一个功能,就是在docker启动的时候,需要执行一段sql脚本初始化数据库,这个需求postgresql的image已经考虑到,只需要把要执行的脚本映射到一个特殊的路径即可。映射后,在container启动的时候,会执行sql.

- ./db.sql:/docker-entrypoint-initdb.d/init.sql

那么最终我们的docker-compose文件可能是这样:

version: '3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=db;Username=postgres;
      - ASPNETCORE_ENVIRONMENT=Development
      - OPENAI_API_KEY=sk-1234567890abcdef1234567890abcdef # REPLACE WITH YOUR OPENAI KEY
    ports:
      - "5000:5000"
    depends_on:
      - db
  db:
    image: bitnami/postgresql:latest
    container_name: pg-container
    restart: always
    environment:
      POSTGRES_USER: postgres
      ALLOW_EMPTY_PASSWORD: yes
      POSTGRES_DB: db
    volumes:
      - ./db.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "5432:5432"

总结

使用ASP.NET Core开发restful api相当方便,而借助容器的强大功能,部署到云环境进行快速验证也得以实现.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/900580.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DDR Study - LPDDR Write and Training

参考来源&#xff1a;JESD209-4B&#xff0c;JESD209-4E LPDDR Initial → LPDDR Write Leveling and DQ Training → LPDDR Read and Training → LPDDR Write and Training → LPDDR Clock Switch → PIM Technical Write Command 基于JEDEC标准中可以看到Write Timing信息…

LC专题:图

文章目录 133. 克隆图 133. 克隆图 题目链接&#xff1a;https://leetcode.cn/problems/clone-graph/?envTypestudy-plan-v2&envId2024-spring-sprint-100 又一次写到这个题目&#xff0c;思路仍然不清晰&#xff0c;给我的感觉是使用递归解题&#xff0c;但是递归具体…

基于springboot企业微信SCRM管理系统源码带本地搭建教程

系统是前后端分离的架构&#xff0c;前端使用Vue2&#xff0c;后端使用SpringBoot2。 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 Mysql5.7 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 系统与功能介绍 基…

雷池社区版有多个防护站点监听在同一个端口上,匹配顺序是怎么样的

如果域名处填写的分别为 IP 与域名&#xff0c;那么当使用进行 IP 请求时&#xff0c;则将会命中第一个配置的站点 以上图为例&#xff0c;如果用户使用 IP 访问&#xff0c;命中 example.com。 如果域名处填写的分别为域名与泛域名&#xff0c;除非准确命中域名&#xff0c;否…

顶点着色网格转换为 UV 映射的纹理化网格

https://dylanebert-instanttexture.hf.space/ 简介 顶点着色是一种将颜色信息直接应用于网格顶点的简便方法。这种方式常用于生成式 3D 模型的构建&#xff0c;例如InstantMesh。然而&#xff0c;大多数应用程序更偏好使用 UV 映射的纹理化网格。 InstantMeshhttps://hf.co/sp…

3D-IC——超越平面 SoC 芯片的前沿技术

“3D-IC”&#xff0c;顾名思义是“立体搭建的集成电路”&#xff0c;相比于传统平面SoC&#xff0c;3D-IC引入垂直堆叠芯片裸片&#xff08;die&#xff09;和使用硅通孔&#xff08;TSV&#xff09;等先进封装技术&#xff0c;再提高性能、降低功耗和增加集成度方面展现了巨大…

H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)

LUA脚本的好处是用户可以根据自己注册的一批API&#xff08;当前TOOL已经提供了几百个函数供大家使用&#xff09;&#xff0c;实现各种小程序&#xff0c;不再限制Flash里面已经下载的程序&#xff0c;就跟手机安装APP差不多&#xff0c;所以在H7-TOOL里面被广泛使用&#xff…

springboot080房屋租赁管理系统的设计与实现(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;房屋租赁管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好…

Java 输入与输出(I\O)之对象流与对象序列化

什么是Java的对象流&#xff1f; Java对象流是用于存储和读取基本数据类型数据或对象数据的输入输出流。 Java的对象流可分为两种&#xff1a; 1&#xff0c;对象输入流类ObjectInputStream 用于从数据源读取对象数据&#xff0c;它是可以读取基本数据类型数据或对象数据的输…

pikachu靶场CSRF-token测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、抓包使用burp生成csrf脚本 四、源代码分析 五、结论 一、测试环境 1、系统环境 渗透机&#xff1a;本机(127.0.0.1) 靶 机&#xff1a;本机(127.0.0.1) 2、使用工具/软件 Burp sui…

python+大数据+基于热门视频的数据分析研究【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

QT 调用QRencode库生成二维码和使用Code128生成简单条形码

目录导读 前言使用Code128生成简单条形码使用QRencode库生成二维码添加QRencode.Pri 模块化 前言 对在QT开发中使用QRencode库生成二维码 和使用Code128生成简单条形码 进行一个学习使用总结。 使用Code128生成简单条形码 ‌Code128条形码是一种高密度条码&#xff0c;广泛应用…

4K双模显示器7款评测报告

4K双模显示器7款评测报告 HKC G27H7Pro 4K双模显示器 ROG华硕 XG27UCG 4K双模显示器 雷神 ZU27F160L 4K双模显示器 泰坦军团 P275MV PLUS 4K双模显示器 外星人&#xff08;Alienware&#xff09;AW2725QF 4K双模显示器 SANC盛色 D73uPro 4K双模显示器 ANTGAMER蚂蚁电竞 …

lvgl

lvgl 目录 lvgl Lvgl移植到STM32 -- 1、下载LVGL源码 -- 2、将必要文件复制到工程目录 -- 3、修改配置文件 将lvgl与底层屏幕结合到一块 -- lvgl也需要有定时器&#xff0c;专门给自己做了一个函数&#xff0c;告诉lvgl经过了多长时间&#xff08;ms&#xff08;毫秒&a…

第三十篇:TCP连接断开过程,从底层说明白,TCP系列五

上一篇《第二十九篇&#xff1a;图解TCP三次握手&#xff0c;看过不会忘&#xff0c;从底层说清楚&#xff0c;TCP系列四》说了TCP的三次握手&#xff0c;接下来我将讲解TCP四次挥手。 既然有连接就有断开&#xff0c;谈到这里&#xff0c;有的同学可能会想&#xff0c;不就是…

log4j 和 logback 冲突解决

很多springboot starter自带logback 如果我们要用log4j就要把logback排除掉 点idea的maven侧栏工具的分析依赖关系 然后我们要选中我们有冲突的模块&#xff0c;搜索logback 这时候我们发现有logback相关的依赖&#xff0c;在点一下&#xff0c;我们就在右边发现&#xff0c;原…

STM32--I2C通信

对于I2C通信会分为两大块来讲解&#xff0c;第一块,就是介绍协议规则,然后用软件模拟的形式来实现协议&#xff0c;第二块,就是介绍STM32的12C外设,然后用硬件来实现协议&#xff0c;因为12C是同步时序,软件模拟协议也非常方便。 在学12C之前,我们已经学习了串口通信&#xff…

openlayers 封装加载本地geojson数据 - vue3

Geojson数据是矢量数据&#xff0c;主要是点、线、面数据集合 Geojson数据获取&#xff1a;DataV.GeoAtlas地理小工具系列 实现代码如下&#xff1a; import {ref,toRaw} from vue; import { Vector as VectorLayer } from ol/layer.js; import { Vector as VectorSource } fr…

蓄电池在线监测系统 各大UPS铅酸蓄电池监测 保障安全

蓄电池的不断普及&#xff0c;确实推动了蓄电池监控和管理技术的持续升级。蓄电池检测系统的研发为我们带来了诸多好处&#xff0c;这些好处主要体现在以下几个方面&#xff1a; 一、提高蓄电池管理的智能化水平 蓄电池检测系统通过实时监测蓄电池的电压、电流、温度等关键参数…

ZEISS ATOS Q蓝光三维扫描仪高效把控零件质量检测【上海沪敖3D】

位于Bengaluru的施耐德电气工厂拥有一流的计量设备&#xff0c;可以检测所有供应商的零件。当时&#xff0c;他们在使用一款激光扫描设备进行质量检测&#xff0c;但是&#xff0c;该设备不便于携带&#xff0c;且检测时需要喷涂大量的显影液。此外&#xff0c;它需要被安装在夹…