基于AI大文本模型的智慧对话开发设计及C#源码实现,实现智能文本改写与智慧对话

文章目录

  • 1.AI 大模型发展现状
  • 2.基于AI服务的智慧对话开发
    • 2.1 大模型API选择
    • 2.2 基于C#的聊天界面开发
    • 2.3 星火大模型API接入
    • 2.4 优化开发界面与显示逻辑
  • 3.源码工程Demo及相关软件下载
  • 参考文献

1.AI 大模型发展现状

端午假期几天,关注到国内的AI大模型厂商近乎疯狂地打起了价格战,这边阿里云刚宣布降价97%,那边百度就宣布两款模型全面免费,好不热闹!据不完全统计,国内已有7家大模型企业“参战”,包括字节跳动、阿里云、百度、腾讯云等互联网大厂,智谱AI、深度求索等AI创企,以及垂直赛道头部玩家科大讯飞,纷纷争夺“最便宜”“最高性价比”大模型这块蛋糕。
在这里插入图片描述
▲国内大模型厂商参与价格战情况(智东西制表,统计于2024年5月27日)
总的来看,各大厂商对降价原因的解释无外乎以下几点:技术突破了,推理成本降低了;为开发者兜底,降低大模型的使用门槛;提升产品竞争力,积累客户。但大模型价格战对产业的影响具有两面性,既能够促使产业格局变化和商业模式创新,也为开发者带来机遇,有利于爆款应用的开发和大模型私有化部署。

2.基于AI服务的智慧对话开发

由于工作关系,涉及到相关文字材料的编制,对于某些材料,选用baidu的文心一言或者Aliyun的通义千问对于简单的工作来说可以提升部分效率,但是基于网页端还是存在一些限制,于是计划假期间利用C#语言+VS2015的win界面开发优势,配合大模型API实现快速的文本改写文字降重以及智慧对话的功能

2.1 大模型API选择

选择讯飞星火大模型,其SparkLite免费为开发者开放,且不限tokens和有效期,提供各类开发的Demo源码,对于新手开发的话也比较友好。
在这里插入图片描述

2.2 基于C#的聊天界面开发

聊天界面开发计划基于Panel、RichTextBox、Button、PictureBox组成。其中Button主要负责模拟发送。
在这里插入图片描述

值得说明的是:Panel部分的聊天窗口由设计如下控件组成,且要支持右键菜单的复制和全选的功能,方便获取消息内容。

功能控件
头像PictureBox
昵称Label
发送时间Label
信息详情RichTextBox
右键菜单ContextMenuStrip

实现的效果如下:
在这里插入图片描述

主窗体源码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //新建聊天控件全局变量
        ChatBubble tsps_chat;

        private void button1_Click(object sender, EventArgs e)
        {

            Image touxiang = (WindowsFormsApplication1.Properties.Resources._001);
            Image touxiang2 = (WindowsFormsApplication1.Properties.Resources._002);
            //发送
            tsps_chat.AddMsg(touxiang2,
                richTextBox1.Text, ChatBubble.MsgPlace.Right, "测试");
            //模拟接收
            tsps_chat.AddMsg(touxiang,
                "你好,我有一个帽衫...",ChatBubble.MsgPlace.Left,"TSPS");

           

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            panel1.VerticalScroll.Visible = true;
            panel1.AutoScroll = true;
            Font ft = new Font("黑体", 12, Font.Style & ~FontStyle.Italic);
            //创建新的聊天窗口(传入panel和font)
            tsps_chat = new ChatBubble(panel1, ft);
        }

    }


}

Panel相关代码如下:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{

    /// <summary>
    /// 聊天窗口展示类
    /// </summary>
    class Class1
    {
    }
    class ChatBubble
    {
        /// <summary>
        /// 生成菜单项
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="img"></param>
        /// <returns></returns>
        private ToolStripMenuItem GetMenuItem(string txt, Image img)
        {
            ToolStripMenuItem menuItem = new ToolStripMenuItem();
            menuItem.Text = txt;
            menuItem.Image = img;
            return menuItem;
        }
        /// <summary>
        /// 菜单项事件响应
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem_Click(object sender, ToolStripItemClickedEventArgs e)
        {
            //ToolStripMenuItem menuSend = sender as ToolStripMenuItem;
            //string selectText = ((RichTextBox)menuSend.).SelectedText;
            //MessageBox.Show(menu.Text);
            //获取对应控件的值
            ContextMenuStrip menu_now = (ContextMenuStrip)sender;
            RichTextBox tb = ((RichTextBox)(menu_now).SourceControl);
            if (((ContextMenuStrip)sender).Items[0] == e.ClickedItem)//全选
            {
                tb.Focus();//设置先焦点定位到当前活动的RichTextBox,
                tb.SelectAll();
            }
            else if (((ContextMenuStrip)sender).Items[1] == e.ClickedItem)//复制
            {
               
                Clipboard.SetDataObject(tb.SelectedText);
            }

        }
        
        public ChatBubble(Panel panel, Font font)
        {
            if (panel.Controls.Count != 0) throw new Exception("指定Panel控件不为空!");
            ChatPlace = panel;
            BubbleFont = font;
            Context_caidan = new ContextMenuStrip();
            MsgMaxLength = panel.Width - (6 * 4 + 35*2 );    // 其中, 四个6为 图片与(容器以及消息文本框)的距离 ,两个35为两侧图片的大小.
            //右键菜单编辑
            Context_caidan.Items.Add("全选");//添加到右键菜单
            Context_caidan.Items.Add("复制");//添加到右键菜单
            //绑定消息
            Context_caidan.ItemClicked += new ToolStripItemClickedEventHandler(toolStripMenuItem_Click);//添加事件
            //Control.ContextMenuStrip = Context_caidan;
        }

        readonly Panel ChatPlace;
        readonly Font BubbleFont;
        readonly ContextMenuStrip Context_caidan;//右键复制菜单

        int NowY = 7;

        readonly int MsgMaxLength;

        public enum MsgPlace
        {
            Left,
            Right
        }              // 气泡创建的位置

        /// <summary>
        /// 根据文本内容设置textbox高度等属性
        /// </summary>
        /// <param name="txt1"></param>
        private void SettxtHeight(RichTextBox textBox1,string showString)
        {
            //属性
            textBox1.Text = showString;
            textBox1.Multiline = true;
            textBox1.WordWrap = true;
            textBox1.Font = BubbleFont;
            textBox1.Width = MsgMaxLength;
            textBox1.BorderStyle = BorderStyle.None;
            textBox1.ContextMenuStrip = Context_caidan;//为文本框添加右键菜单
            textBox1.ReadOnly = true;
            //尺寸参数
            int txtHeight = 22;//设置单行的行高
            int MaxLineCount = 20;//设置最大行数
            Size size = TextRenderer.MeasureText(textBox1.Text, textBox1.Font);
            int itxtLine = size.Width / textBox1.Width + textBox1.Lines.Count() + 1;
            if (itxtLine > MaxLineCount) { itxtLine = MaxLineCount; }
            itxtLine -= 1;
            textBox1.Height = txtHeight * itxtLine;
            
            
        }

        public void AddMsg(Image Photo, string Text, MsgPlace Place, string Name)
        {
            if (ChatPlace.Controls.Count > 4*51) //仅保留近51条消息
            {
                ChatPlace.Controls.Clear();
                NowY = 7;
            }
            if (ChatPlace.Controls.Count != 0)
            {
                NowY = ChatPlace.Controls[ChatPlace.Controls.Count - 2].Location.Y
                    + ChatPlace.Controls[ChatPlace.Controls.Count - 1].Height + 35;//间隔控制
            }
            
            PictureBox photo = new PictureBox();                // 头像
            Label nickname = new Label();                       // 昵称
            Label sendtime = new Label();
            // Label msg = new Label();
            RichTextBox msg = new RichTextBox();
            
            

            photo.Size = new Size(35, 35);
            photo.SizeMode = PictureBoxSizeMode.StretchImage;
            photo.Image = Photo;

            nickname.AutoSize = true;
            nickname.MaximumSize = new Size(0, 0);
            nickname.Font = BubbleFont;
            nickname.Text = Name;

            //获取当前时间
            string timenow = System.DateTime.Now.ToString("T");
            sendtime.AutoSize = true;
            sendtime.MaximumSize = new Size(0, 0);
            sendtime.Font = BubbleFont;
            sendtime.Text = timenow;

            //msg.AutoSize = true;
            //msg.Font = BubbleFont;
            //msg.MaximumSize = new Size(MsgMaxLength, 0);
            // msg.Text = Text;
            //msg.BorderStyle = BorderStyle.None;
            SettxtHeight(msg,Text);//自动调整文本框大小
           

            ChatPlace.Controls.Add(nickname);
            ChatPlace.Controls.Add(sendtime);
            ChatPlace.Controls.Add(photo);
            ChatPlace.Controls.Add(msg);

            if (Place == MsgPlace.Left)
            {
                msg.BackColor = Color.LightGreen;
                photo.Location = new Point(7, NowY);
                sendtime.Location = new Point(ChatPlace.Width/2-45, NowY);
                nickname.Location = new Point(photo.Location.X + photo.Width + 6, NowY);
                msg.Location = new Point(nickname.Location.X, NowY + nickname.Size.Height);
            }
            else
            {
                msg.BackColor = Color.LightSkyBlue;
                photo.Location = new Point(ChatPlace.Width - 7 - 35 - 10, NowY);
                sendtime.Location = new Point(ChatPlace.Width/2 -45 , NowY);
                nickname.Location = new Point(photo.Location.X - 7 - nickname.Width - 17, NowY);
                msg.Location = new Point(photo.Location.X - msg.Width - 10, NowY + nickname.Size.Height);
                // 这里的减去10是除去滚动条的宽度
            }
            //panel滚动条到最下方
            Point newPoint = new Point(0, ChatPlace.Height - ChatPlace.AutoScrollPosition.Y);
            ChatPlace.AutoScrollPosition = newPoint;
        }
    }        // 简易聊天气泡

}

2.3 星火大模型API接入

使用如下C#代码接入讯飞星火大模型API

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using Newtonsoft.Json;
using System.Net.WebSockets;
using System.Threading;
using Newtonsoft.Json.Linq;
using System.Text.Json;

/**
 * 星火认知大模型 WebAPI 接口调用示例 接口文档(必看):https://www.xfyun.cn/doc/spark/Web.html
 * 错误码链接:https://www.xfyun.cn/doc/spark/%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E.html (code返回错误码时必看)
 * @author iflytek
 */
namespace Webiat
{
    class Program
    {
        static ClientWebSocket webSocket0;
        static CancellationToken cancellation;
        // 应用APPID(必须为webapi类型应用,并开通星火认知大模型授权)
        const string x_appid = "XXXXXXXX";
        // 接口key(webapi类型应用开通星火认知大模型后,控制台--我的应用---星火认知大模型---相应服务的apikey)
        const string api_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        // 接口密钥(webapi类型应用开通星火认知大模型后,控制台--我的应用---星火认知大模型---相应服务的apisecret)
        const string api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

        static string hostUrl = "https://spark-api.xf-yun.com/v1.1/chat";
        async public static void Tasker()
        {
            
            string authUrl = GetAuthUrl();
            string url = authUrl.Replace("http://", "ws://").Replace("https://", "wss://");
            using (webSocket0 = new ClientWebSocket())
            {
                try
                {
                    await webSocket0.ConnectAsync(new Uri(url), cancellation);

                    JsonRequest request = new JsonRequest();
                    request.header = new Header()
                                    {
                                        app_id = x_appid,
                                        uid = "12345"
                                    };
                    request.parameter = new Parameter()
                                        {
                                            chat = new Chat()
                                            {
                                                domain = "general",//模型领域,默认为星火通用大模型
                                                temperature = 0.5,//温度采样阈值,用于控制生成内容的随机性和多样性,值越大多样性越高;范围(0,1)
                                                max_tokens = 1024,//生成内容的最大长度,范围(0,4096)
                                            }
                                        };
                    request.payload = new Payload()
                                        {
                                            message = new Message()
                                            {
                                                text = new List<Content>
                                                {
                                                    new Content() { role = "user", content = "你是谁" },
                                                    // new Content() { role = "assistant", content = "....." }, // AI的历史回答结果,这里省略了具体内容,可以根据需要添加更多历史对话信息和最新问题的内容。
                                                }
                                            }
                                        };

                    string jsonString = JsonConvert.SerializeObject(request);
                    //连接成功,开始发送数据
                    

                    var frameData2 = System.Text.Encoding.UTF8.GetBytes(jsonString.ToString());

                    
                    webSocket0.SendAsync(new ArraySegment<byte>(frameData2), WebSocketMessageType.Text, true, cancellation);
                   
                    // 接收流式返回结果进行解析
                    byte[] receiveBuffer = new byte[1024];
                    WebSocketReceiveResult result = await webSocket0.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), cancellation);
                    String resp = "";
                    while (!result.CloseStatus.HasValue)
                    {
                        if (result.MessageType == WebSocketMessageType.Text)
                        {
                            string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, result.Count);
                            //将结果构造为json
                            
                            JObject jsonObj = JObject.Parse(receivedMessage);
                            int code = (int)jsonObj["header"]["code"];
                            
                            
                            if(0==code){
                                int status = (int)jsonObj["payload"]["choices"]["status"];
                                

                                JArray textArray = (JArray)jsonObj["payload"]["choices"]["text"];
                                string content = (string)textArray[0]["content"];
                                resp += content;

                                if(status != 2){
                                    Console.WriteLine($"已接收到数据: {receivedMessage}");
                                }
                                else{
                                    Console.WriteLine($"最后一帧: {receivedMessage}");
                                    int totalTokens = (int)jsonObj["payload"]["usage"]["text"]["total_tokens"];
                                    Console.WriteLine($"整体返回结果: {resp}");
                                    Console.WriteLine($"本次消耗token数: {totalTokens}");
                                    break;
                                }

                            }else{
                                Console.WriteLine($"请求报错: {receivedMessage}");
                            }
                                

                        }
                        else if (result.MessageType == WebSocketMessageType.Close)
                        {
                            Console.WriteLine("已关闭WebSocket连接");
                            break;
                        }

                        result = await webSocket0.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), cancellation);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }
        // 返回code为错误码时,请查询https://www.xfyun.cn/document/error-code解决方案
        static string GetAuthUrl()
        {
            string date = DateTime.UtcNow.ToString("r");

            Uri uri = new Uri(hostUrl);
            StringBuilder builder = new StringBuilder("host: ").Append(uri.Host).Append("\n").//
                                    Append("date: ").Append(date).Append("\n").//
                                    Append("GET ").Append(uri.LocalPath).Append(" HTTP/1.1");

            string sha = HMACsha256(api_secret, builder.ToString());
            string authorization = string.Format("api_key=\"{0}\", algorithm=\"{1}\", headers=\"{2}\", signature=\"{3}\"", api_key, "hmac-sha256", "host date request-line", sha);
            //System.Web.HttpUtility.UrlEncode

            string NewUrl = "https://" + uri.Host + uri.LocalPath;

            string path1 = "authorization" + "=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(authorization));
            date = date.Replace(" ", "%20").Replace(":", "%3A").Replace(",", "%2C");
            string path2 = "date" + "=" + date;
            string path3 = "host" + "=" + uri.Host;

            NewUrl = NewUrl + "?" + path1 + "&" + path2 + "&" + path3;
            return NewUrl;
        }




        public static string HMACsha256(string apiSecretIsKey, string buider)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(apiSecretIsKey);
            System.Security.Cryptography.HMACSHA256 hMACSHA256 = new System.Security.Cryptography.HMACSHA256(bytes);
            byte[] date = System.Text.Encoding.UTF8.GetBytes(buider);
            date = hMACSHA256.ComputeHash(date);
            hMACSHA256.Clear();

            return Convert.ToBase64String(date);

        }
        
        
        static void Main(string[] args)
        {
            Tasker();
            Console.ReadLine();
        }

    }
}



//构造请求体
public class JsonRequest
{
    public Header header { get; set; }
    public Parameter parameter { get; set; }
    public Payload payload { get; set; }
}

public class Header
{
    public string app_id { get; set; }
    public string uid { get; set; }
}

public class Parameter
{
    public Chat chat { get; set; }
}

public class Chat
{
    public string domain { get; set; }
    public double temperature { get; set; }
    public int max_tokens { get; set; }
}

public class Payload
{
    public Message message { get; set; }
}

public class Message
{
    public List<Content> text { get; set; }
}

public class Content
{
    public string role { get; set; }
    public string content { get; set; }
}

2.4 优化开发界面与显示逻辑

最终调整了实时显示以及界面展示逻辑如下效果
1.获取的数据可以实时显示并自动调整控件大小;
2.可以正常通过按钮进行交互控制;
3.增加进度条用于显示实时状态;
4.支持个人的账号登录。
请添加图片描述
请添加图片描述

3.源码工程Demo及相关软件下载

下载1:讯飞星火大模型C#接入Demo
下载2: C#聊天窗口界面Demo开发
下载3: 打包好的程序,可直接使用: TSPS V32程序,支持讯飞大模型等API接入、论文降重、文本改写、智慧AI对话 或 蓝奏云下载

注:对于上述(3)中打包的程序,若程序打开时显示“Window已保护你的电脑”可以:
1.点击弹窗的“更多信息”
2.点击仍要运行
3.在弹窗中点击“是”即可打开

参考文献

https://www.thepaper.cn/newsDetail_forward_27521760
https://blog.csdn.net/qq_20051033/article/details/104889215?spm=1001.2014.3001.5506

请添加图片描述

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

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

相关文章

时序数据库是Niche Market吗?

引言 DB-Engines的流行程度排行从其评估标准[4]可以看出完全不能够做为市场规模的评估标准。甚至于在知道市场规模后可以用这个排行作为一个避雷手册。毕竟现存市场小&#xff0c;可预见增长规模小&#xff0c;竞争大&#xff0c;创新不足&#xff0c;那只能卷价格&#xff0c…

冲刺面试加油

1、HTML语义化&#xff1f; 对于开发者而言&#xff0c;语义化标签有着更好的页面结构&#xff0c;有利于代码的开发编写和后期的维护。 对于用户而言&#xff0c;当网络卡顿时有良好的页面结构&#xff0c;有利于增加用户的体验。 对于爬虫来说&#xff0c;有利于搜索引擎的…

你还不知道无线PLC?

随着技术的不断发展&#xff0c;工业控制系统也在经历着革新。无线PLC&#xff08;Programmable Logic Controller&#xff0c;可编程逻辑控制器&#xff09;是一种结合了无线通讯技术和传统PLC系统的创新型技术。它为工业自动化提供了一种更灵活、更便捷的解决方案&#xff0c…

跟我学,数据结构和组原真不难

我个人认为408中计算机组成原理和数据结构最难 难度排行是计算机组成原理>数据结构>操作系统>计算机网络。 计算机组成原理比较难的原因是&#xff0c;他涉及的硬件的知识比较多&#xff0c;这对于大家来说难度就很高了&#xff0c;特别是对于跨考的同学来说&#x…

保姆级讲解 Linux下FTP服务器的搭建、配置与管理

本来目录很长的 因为感觉不太美观 所以小标题都删掉了 本文介绍了 本地用户的FTP服务器搭建实例匿名用户的FTP服务器搭建实例虚拟用户的FTP服务器搭建实例企业常见类型搭建实验 配置与管理FTP服务器 配置与管理FTP服务器一、FTP相关知识二、项目设计与准备三、项目实施四、认识…

架构设计-web项目中跨域问题涉及到的后端和前端配置

WEB软件项目中经常会遇到跨域问题&#xff0c;解决方案早已是业内的共识&#xff0c;简要记录主流的处理方式&#xff1a; 跨域感知session需要解决两个问题&#xff1a; 1. 跨域问题 2. 跨域cookie传输问题 跨域问题 解决跨域问题有很多种方式&#xff0c;如使用springboot…

打造你的博客帝国:DjangoBlog带你飞向国际舞台!

你的网站加载速度还在慢如蜗牛吗&#xff1f;将为你揭开网站速度提升的神秘面纱。从缓存策略到数据库优化&#xff0c;再到高效的代码实践&#xff0c;我们深入探讨了如何让DjangoBlog飞速运行。不仅如此&#xff0c;我们还提供了实用的监控和日志管理技巧&#xff0c;确保你的…

【Linux】—— 线程控制的基本介绍

目录 &#xff08;一&#xff09;POSIX线程库 &#xff08;二&#xff09;创建线程 2.1 线程ID及进程地址空间布局 &#xff08;三&#xff09;线程终止 &#xff08;四&#xff09;分离线程 &#xff08;一&#xff09;POSIX线程库 POSIX线程库&#xff08;POSIX Thread…

PySpark教程(001):基础准备与数据输入

PySpark 学习目标 了解什么是Spark、PySpark了解为什么学习PySpark了解如何和大数据开发方向进行衔接 Spark是什么&#xff1f; Apache Spark是用于大规模数据处理的统一分析引擎。 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器…

Go微服务: 理解分布式锁

概述 我们先看一个场景&#xff0c;到了双11&#xff0c;我们的商户又开始卖商品啦但是&#xff0c;我们的库存是有限的&#xff0c;如果超卖了&#xff0c;可能平台就会涉及相关法律责任了所以&#xff0c;我们的库存扣除问题&#xff0c;一定是一个非常经典的问题 先看上图&…

LabVIEW电池测试系统

1. 背景 随着电动汽车、可再生能源等领域的迅速发展&#xff0c;电池作为能源储存和释放的核心组件&#xff0c;其性能评估变得尤为重要。电池的充放电性能、容量、循环寿命等参数直接影响着设备的工作性能和使用寿命。因此&#xff0c;设计一套全面、准确的电池测试系统对于提…

orbslam2代码解读(2):tracking跟踪线程

书接上回&#xff0c;mpTracker->GrabImageMonocular(im,timestamp)函数处理过程&#xff1a; 如果图像是彩色图&#xff0c;就转成灰度图如果当前帧是初始化的帧&#xff0c;那么在构建Frame的时候&#xff0c;提取orb特征点数量为正常的两倍&#xff08;目的就是能够在初…

Android JobService启动系统源码分析

以下就JobService的执行流程,系统层实现进行详解 入口点在JobScheduler.scheduler 系统层JobScheduler是个抽象类,它的实现类是JobScheduler mBinder,一看就知道这里面肯定是跨进程了。它的服务端在JobSchedulerService里面,具体 为什么请看系统服务器启动流程相关文章,…

【传知代码】上下位关系自动检测方法(论文复现)

前言&#xff1a;在信息爆炸的时代&#xff0c;我们每天都沉浸在海量的数据和信息中。随着互联网技术的飞速发展&#xff0c;如何从这些信息中准确、高效地提取出有用的知识&#xff0c;成为了当下研究的热点。其中&#xff0c;上下位关系&#xff08;也称为层级关系或种属关系…

康姿百德集团公司官网床垫价格透明,品质睡眠触手可及

选择康姿百德床垫&#xff0c;价格透明品质靠谱&#xff0c;让你拥有美梦连连 在当今社会&#xff0c;良好的睡眠质量被越来越多的人所重视。睡眠不仅关系到我们第二天的精力状态&#xff0c;更长远地影响着我们的身体健康。因此&#xff0c;选择一款合适的床垫对于获得优质睡…

Android Studio Jellyfish版本修改project使用特定jdk版本的步骤

android studio总是把这些东西改来改去让人十分恼火&#xff0c;IDE本身改来改去就让人无法上手就立即工作&#xff0c;很多时间浪费在IDE和gradle的配置和奇奇怪怪现象的斗智斗勇上&#xff0c;搞Android是真的有点浪费生命。一入此坑深不见底 jellyfish版安卓studio已经无法通…

Python模块导入,别out了,看看这些高级玩法!

目录 1、基础导入&#xff1a;import语句 &#x1f4da; 1.1 直接导入模块 1.2 导入模块别名 1.3 从模块导入特定属性 2、高级导入&#xff1a;from...import &#x1f9f0; 2.1 选择性导入模块成员 2.2 嵌套模块导入 2.3 避免命名冲突策略 3、动态导入&#xff1a;imp…

Mysql基础-多表查询

Mysql基础-多表查询 文章目录 Mysql基础-多表查询1 多表关系1.1 一对多1.2 多对多1.3 一对一 2 多表查询概述2.1 多表查询分类 3 内连接4 外连接5 自连接6 联合查询-union union all7 子查询7.1 标量子查询7.2 列子查询7.3 行子查询7.4 表子查询 1 多表关系 项目开发中&#xf…

Jenkins构建打包部署前端Vue项目至Nginx

一. 安装jenkins 基于DockerJenkins实现自动部署SpringBootMaven项目-CSDN博客 二. 安装NodeJs插件并配置 显示上面两行则表示安装成功, 然后回到首页, 点击’系统管理’->‘全局工具配置’: 配置node.js 三. 创建jenkins项目 1、创建项目 2、配置gitee 3、配置源码 4、…

网络学了点socket,写个聊天室,还得改进

目录 第一版: common 服务端: 客户端 第一版问题总结: 第二版 服务端: 客户端: 改进: Windows客户端 一些小问题 还可以进行的改进 这篇文章我就先不讲网络基础的东西了,我讲讲在我进行制作我这个拉跨聊天室中遇到的问题,并写了三版代码. 第一版: common #pragm…