以腾讯混元模型为例,在管理平台上集成一个智能助手

背景

前几天,公司的同事们一起吃了个饭,餐桌上大家聊到大模型的落地场景。我个人在去年已经利用百度千帆平台写过案例,并发过博客(传送门👉:利用文心千帆打造一个属于自己的小师爷),只不过那时候没有再继续深入真正做好大模型在项目上的落地。

这次刚刚开发完的一个考试系统,里面正好有一个落地场景,利用AI的能力来生成题库的解析内容,可以大幅提高效率。

准备工作

因为公司的云服务商是腾讯,所以我这次使用的是腾讯混元大模型,在开始集成工作前,要先去腾讯云的控制台开通相关的服务。

事实上,所有集成任何第三方云端大模型的步骤都差不多,这一步我就不多说了,参照文档操作即可(传送门👉:腾讯混元大模型)。

需要注意的是,新申请的服务,可以领取一定的免费额度,而且lite模型目前是一直免费的,这点和各家也都差不多。在这里插入图片描述
在这里插入图片描述

集成

接入方式

大模型集成到项目的方式有很多,有的可能就是一个模块,有的可能是一个独立服务,总之就是根据实际的项目情况,接入的方式,呈现的结果都是不一样的。

我这边把大模型在系统里的定位就是一个随叫随到的智能助手,在整个后台管理工作的场景中,都可以方便的和大模型交互。

业务代码之前

配置

"AiConfigs": [
  {
    "IsOpenaiApi": "yes",
    "Model": "moonshotai",
    "SecretKey": "",
    "SecretId": "",
    "AppId": "",
    "ApiKey": "sk-{xxxxxxxxxx}"
  },
  {
    "IsOpenaiApi": "no",
    "Model": "hunyuan",
    "SecretId": "{xxx}",
    "SecretKey": "{xxx}",
    "AppId": "xxx",
    "ApiKey": ""
  }

这里,我是把请求模型的密钥参数放到配置文件里了,事实上,生产环境中更推荐的做法是把密钥参数放到系统的环境变量里更加安全。

这里这样配置是为以后扩展做准备,此次集成的是混元大模型的sdk,申请的方式是按sdk的方式申请,云服务商一般会给到一组密钥对,包括secretid,secretkey等,而类似openai api的方式,是只有一个appkey,所以我这里是这样定义的参数,方便后续反序列化。

其实目前各家基本都支持openapi的方式了,但因为我这里只有公司腾讯云的子账号,申请openapi风格的key需要主账号,而且要主账号提供mfa验证码,我有点社恐,没去找主账号持有人沟通,就暂时没用~

但我还是申请了一个个人的月之暗面(moonshot)账户(传送门👉:Moonshot AI),并获得了一个openapi风格的apikey,确保两种接入方式都支持。

定义对照模型

public class AiConfig
{
    [JsonProperty("IsOpenaiApi")]
    public string IsOpenaiApi { get; set; }

    [JsonProperty("Model")]
    public string Model { get; set; }
    [JsonProperty("SecretKey")]
    public string SecretKey {  get; set; }
    [JsonProperty("SecretId")]
    public string SecretId { get; set; }
    [JsonProperty("AppId")]
    public string AppId { get; set; }

    /// <summary>
    /// IsOpenaiApi为yes时,ApiKey为必填项
    /// </summary>
    [JsonProperty("ApiKey")]
    public string ApiKey { get; set; }
    
    //public string Token { get; set; }
}

这里的就是参照配置文件的格式,创建对照模型,方便后续的序列化工作。

创建工厂类

public class AiConfigFactory
{
    private readonly List<AiConfig> _aiConfigs;

    public AiConfigFactory(List<AiConfig> aiConfigs)
    {
        _aiConfigs = aiConfigs;
    }

    public AiConfig GetConfigByModel(string Model)
    {
        return _aiConfigs.FirstOrDefault(config => config.Model.Equals(Model, StringComparison.OrdinalIgnoreCase));
    }
}

注入服务

private static void ConfigureAi(this IServiceCollection services, IConfiguration configuration)
{
    var aiConfigs = new List<AiConfig>();
    configuration.GetSection("AiConfigs").Bind(aiConfigs);
    // 注册工厂为单例服务
    services.AddSingleton(new AiConfigFactory(aiConfigs));
    //...其他配置
}
...
//这里我是把每个中间件都分离成一个小模块,配置完成后,在入口处统一注册
//像这样
builder.Services.ConfigureAi(_configuration);

其他工作

因为是要全场景的运行ai助手,得充分发挥系统基础设施的能力,所以这里还有根据情况注入Redis,消息队列,数据库等中间件,这部分代码都是很常见的,不再赘述。

接入混元SDK

准备工作就绪以后,就可以引入混元sdk了,这部分就是标准的调参工作,非常简单,大家可以跳过本节,直接参照混元的接口文档(传送门👉:混元大模型),然后按照自己喜欢的放方式完成对接.

我这里简单介绍下

安装必要sdk

安装混元sdk,可以直接在vs的nuget包管理器搜索TencentCloudSDK.Hunyuan关键字安装,或者直接通过下面方式

# 命令行
dotnet add package TencentCloudSDK.Hunyuan
# 或者vs里打开程序包管理器控制台
Install-Package TencentCloudSDK.Hunyuan

创建控制器

这里我只给出几个关键的业务代码

//chat接口
[HttpPost,ValidateAntiForgeryToken]
public async Task<IActionResult> SimpleChat(ChatModel chatModel)
{
    if (string.IsNullOrWhiteSpace(chatModel.prompt))
        return Json(_resp.error("无输入"));
    
    try
    {
        if(string.IsNullOrEmpty(chatModel.admin))
            chatModel.admin = adminId;
        await _capPublisher.PublishAsync(CapConsts.PREFIX + "GetHunyuanResponse", chatModel);
        return Json(_resp.success(0, "ok"));
    }
    catch (Exception e)
    {
        Assistant.Logger.Error(e);
        return Json(_resp.error("获取响应失败," + e.Message));
    }
}

[HttpGet("airesp")]
public async Task AiResponseSse(string admin)
{
    Response.Headers["Content-Type"] = "text/event-stream";
    Response.Headers["Cache-Control"] = "no-cache";
    if (HttpContext.Request.Protocol.StartsWith("HTTP/1.1"))
    {
        Response.Headers["Connection"] = "keep-alive";
    }
    try
    {
        if (string.IsNullOrEmpty(admin))
            admin = adminId;
        while (true)
        {
            await Task.Delay(50);
            // 从通道中读取消息(这里等待消息到来)
            if (!await _redisCachingProvider.KeyExistsAsync("cacheId" + admin))
                return;
            var message = await _redisCachingProvider.LPopAsync<string>("cacheId" + admin);
            if (string.IsNullOrEmpty(message))
                continue;
            // 按照SSE协议格式发送数据到客户端
            await Response.WriteAsync($"data:{message}\n\n");
            await Response.Body.FlushAsync();

        }

    }
    catch (Exception ex)
    {
        // 可以记录异常等处理
        Console.WriteLine(ex.Message);
    }
}

[NonAction]
[CapSubscribe(CapConsts.PREFIX + "GetHunyuanResponse")]
public async Task GetHunyuanResponse(ChatModel chatModel)
{
    try
    {
        Assistant.Logger.Warning("开始请求混元接口");
        var commonParams = new HunyuanCommonParams();
        // 实例化一个client选项,可选的,没有特殊需求可以跳过
        ClientProfile clientProfile = new ClientProfile();
        // 实例化一个http选项,可选的,没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.Endpoint = commonParams.Endpoint;
        clientProfile.HttpProfile = httpProfile;

        // 实例化要请求产品的client对象,clientProfile是可选的
        HunyuanClient client = new HunyuanClient(_cred, commonParams.Region, clientProfile);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        ChatCompletionsRequest req = new ChatCompletionsRequest();
        req.Model = HunyuanModels.Lite;
        if (!string.IsNullOrWhiteSpace(chatModel.model))
            req.Model = chatModel.finalModel;
        Message message1 = new Message();
        message1.Role = "user";
        message1.Content = chatModel.prompt;
        req.Messages = [message1];
        req.Stream = true;
        ChatCompletionsResponse resp = await client.ChatCompletions(req);
        // 输出json格式的字符串回包
        if (resp.IsStream)
        {
            // 流式响应
            foreach (var e in resp)
            {
                Assistant.Logger.Debug(e.Data);
                await _redisCachingProvider.RPushAsync("cacheId" + chatModel.admin, new List<string>() { e.Data });
            }
        }
        else
        {
            // 非流式响应
            Assistant.Logger.Debug(JsonConvert.SerializeObject(resp));
        }
    }
    catch (Exception ex)
    {
       Assistant.Logger.Error(ex);
    }
    finally
    {
        await _redisCachingProvider.KeyExpireAsync("cacheId" + chatModel.admin, 600);
    }
}

简单解释下,这段代码,主要分3个逻辑来处理云端返回的消息,

第一步是前端通过接口,把结构化的消息提交到服务端,也就是SimpleChat接口
第二步,SimpleChat接收到消息后,立刻返回,并发布任务让服务端后台开始请求混元的服务端,获取相应结果,并暂存到Redis队列里
第三步是服务端通过SSE链接的方式把Redis队列里的消息,推到本地客户端
事实上,不暂存直接推也是可以的,我这里因为有其他业务交叉,所以这样处理了一下。 另外,对接混元sdk的方法,还有一种common sdk的方式,更加轻量级,也就是把大量实例化和序列化的工作交给混元的服务器,我们自己的服务端只承担点传输的工作,对性能的优化也是有好处的,而且也能更方便的把sdk的代码写法改成openai api的方式,建议后续直接使用common sdk的方式。

前端代码就不在展示了,按照喜好实现即可

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

演示视频

总结

目前来说只是初步接入到了系统,样式上还些问题需要处理,而且目前只支持文字模式,不支持图片,也没有完全和业务绑定,后续会把一些常见的场景,比如题目解析,智能分析用户的考卷等场景和ai深度结合。

好了,基本就这样了

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

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

相关文章

软件实验室认可|实验室比对的形式与方法

实验室比对是软件测试实验室在申请软件实验室认可必须要做的一类质量控制活动。实验室比对包括实验室间比对&#xff0c;和实验室内比对。实验室间比对指的是按照预先规定的条件&#xff0c;由两个或多个实验室对相同或类似的物品进行测量或检测的组织、实施和评价。实验室内比…

酷克数据携手江西移动入选“星河(Galaxy)”数据库潜力案例

2024 年 12 月 18 - 19 日&#xff0c;为推动打造行业交流平台&#xff0c;驱动产业创新共荣&#xff0c;大数据技术标准推进委员会以“数据重塑价值 智能链接未来”为主题&#xff0c;在北京召开为期两天的“2024 数据资产管理大会”。 在会上&#xff0c;第八届大数据“星河&…

【Verilog】UDP用户原语

User-defined primitives 概述基本语法组合逻辑的UDP时序逻辑的UDPUDP 符号表 Verilog HDL&#xff08;简称 Verilog &#xff09;是一种硬件描述语言&#xff0c;用于数字电路的系统设计。可对算法级、门级、开关级等多种抽象设计层次进行建模。 Verilog 不仅定义了语法&…

《Java核心技术I》Swing中滚动窗格

滚动窗格 Swing中文本区没有滚动条&#xff0c;如需要&#xff0c;可以将文本区放在 滚动窗格(scrollpane)中。 textArea new JTextArea(8,40); var scrollPane new JScrollPane(textArea); 添加到滚动窗格不是文本区特有的&#xff0c;所有组件都可以。 注释&#xff1a;JTe…

Node.js day-01

01.Node.js 讲解 什么是 Node.js&#xff0c;有什么用&#xff0c;为何能独立执行 JS 代码&#xff0c;演示安装和执行 JS 文件内代码 Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff0c;因为这个特点&#xff0c;它可以用来编写服务器后端…

排序算法(7):堆排序

问题 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 堆排序 堆排序是一种基于堆数据结构的排序算法。堆是一个近似完全二叉树的结构&#xff0c;即除了最后一层外&#xff0c;每一层都必须填满&#xff0c;且最后一层从左往右填充。 堆可以分为大根堆和小根堆。在大根堆中&…

操作系统如何管理进程所用的资源

PCB 操作内核的作用 进程与模式的切换 软中断——相当于审核——审核有没有访问权限什么的 操作系统以什么方式提供服务&#xff1f; 进程的创建和终止 线程 七状态图&#xff0c;挂起

罗德与施瓦茨NRP33SN,一款独立、特性齐全的功率探头

罗德与施瓦茨NRP33SN功率探头概述 ROHDE & SCHWARZ NRP33S 三路二极管功率传感器 罗德与施瓦茨 NRP33S 三路二极管功率传感器是一款独立 、特性齐全的仪器。它们可以通过罗德与施瓦茨 NRP2 基 本单元、通过 USB 的笔记本电脑/PC 以及许多罗德与施瓦 茨仪器&#xff08;例如…

uniapp自定义树型结构数据弹窗,给默认选中的节点,禁用所有子节点

兼容H5、安卓App、微信小程序 实现逻辑&#xff1a;给默认选中节点的所有子节点添加一个disabled属性&#xff0c;以此禁用子节点。 /components/sonTreeNode/sonTreeNode.vue 封装成组件 <template><view><view :class"[item,item.is_level1?pL1:item…

运维工程师面试系统监控与优化自动化与脚本云计算的理解虚拟化技术的优点和缺点

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

【GCC】2015: draft-alvestrand-rmcat-congestion-03 机器翻译

腾讯云的一个分析,明显是看了这个论文和草案的 : 最新的是应该是这个 A Google Congestion Control Algorithm for Real-Time Communication draft-ietf-rmcat-gcc-02 下面的这个应该过期了: draft-alvestrand-rmcat-congestion-03

web自动化测试知识总结

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、自动化测试基本介绍 1、自动化测试概述&#xff1a; 什么是自动化测试&#xff1f;一般说来所有能替代人工测试的方式都属于自动化测试&#xff0c;即通过工…

进程间通信方式---消息队列(System V IPC)

进程间通信方式—消息队列&#xff08;System V IPC&#xff09; 文章目录 进程间通信方式---消息队列&#xff08;System V IPC&#xff09;消息队列1.消息队列进程间通信原理2.msgget 系统调用3.msgsnd 系统调用4.msgrcv 系统调用5.msgctl 系统调用6.函数使用案例7.实现生产者…

python学opencv|读取图像(十七)认识alpha通道

【1】引言 前序学习进程中&#xff0c;我们已经掌握了RGB和HSV图像的通道拆分和合并&#xff0c;获得了很多意想不到的效果&#xff0c;相关链接包括且不限于&#xff1a; python学opencv|读取图像&#xff08;十二&#xff09;BGR图像转HSV图像-CSDN博客 python学opencv|读…

Unity Post请求发送fromdata数据content-type

wwwfrom 的 headers["Content-Type"]修改 错误代码&#xff1a; WWWForm form new WWWForm(); if (form.headers.ContainsKey("Content-Type")) {string boundary string.Format("--{0}", DateTime.Now.Ticks.ToString("x"));form…

服务平滑发布与线上验证

发布策略可分为&#xff1a; 蓝绿发布&#xff1a;将新版本服务器全部发好后&#xff0c;将旧版本服务器的流量统一切换到新版本上灰度发布&#xff08;金丝雀发布&#xff09;&#xff1a;是一种滚动发布方式&#xff0c;首先部署部分新版本服务器&#xff0c;将部分流量切到…

【数据安全】如何保证其安全

数据安全风险 数字经济时代&#xff0c;数据已成为重要的生产要素。智慧城市、智慧政务的建设&#xff0c;正以数据为核心&#xff0c;推动城市管理的智能化和公共服务的优化。然而&#xff0c;公共数据开放共享与隐私保护之间的矛盾日益凸显&#xff0c;如何在确保数据安全的…

ai论文生成器:分享8款AI一键生成论文的写作软件

在撰写毕业论文的过程中&#xff0c;高效利用各类软件工具可以极大地提升写作效率与质量。以下是八个免费的神器软件工具&#xff0c;它们各自在论文撰写、文献管理、语法校对、数据可视化等方面发挥着重要作用。希望这些推荐能帮助你顺利完成毕业论文的写作。 千笔AI论文&…

白话AI大模型(LLM)原理

大模型&#xff08;例如 GPT-4或类似的深度学习模型&#xff09;是基于神经网络的系统&#xff0c;用于理解、生成文本、图像或其他数据类型。其工作原理可以分为以下几个核心步骤&#xff0c;我将通过易于理解的例子逐一解释。 1. 神经网络的基本概念 大模型背后有一个非常庞…

数据压缩比 38.65%,TDengine 重塑 3H1 的存储与性能

小T导读&#xff1a;这篇文章是“2024&#xff0c;我想和 TDengine 谈谈”征文活动的三等奖作品之一。作者通过自身实践&#xff0c;详细分享了 TDengine 在高端装备运维服务平台中的应用&#xff0c;涵盖架构改造、性能测试、功能实现等多个方面。从压缩效率到查询性能&#x…