从零开始开发自己的chatgpt平台 之 http客户端和服务端

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、关于开发语言和使用的库二、chatgpt服务端三、chatgpt客户端总结 如果有问题可以联系我**:https://gitee.com/xiaoyuren/gpt3 前言 ` ChatGPT是一个基于GPT(GPT-3.5、GPT-4.0、GPT-5.0)架构的大型语言模型,用于聊天和自然语言处理。它由OpenAI开发,并在许多应用程序中得到广泛使用。本文将为新手介绍ChatGPT的开发过程,包括chatgpt服务端和客户端的实现。可以自己使用,也可以提供服务给别人使用。关于API参数前面2篇已经介绍了 这里就不介绍了。 如果不了解可以看: chatgpt API接口中文说明介绍(一) chatgpt API接口中文说明介绍(二) 一、关于开发语言和使用的库 任何语言只要可以发送POST请求都可以进行开发,本文使用python进行开发,服务端的使用的是sanic库,你也可以使用其他的库 如:fastapi和flask等。客户端使用的是HTML 。用什么语言可自行选择,大同小异。如果你的服务端使用的是PHP,因为 PHP局限性,所以可以使用swoole或者workerman这种框架去开发,尤其是以后开发流式传输(steam)。 本篇讲一下 普通的chatgpt服务端和客户端的开发,后面2篇讲一下websocket服务端客户端和SSE客户端服务端开发 二、chatgpt服务端 import asyncio import time from sanic import Sanic from sanic.response import json import openai app = Sanic(__name__) openai.api_key = 'sk-xxxxxxxxxxxx' @app.route("/gpt", methods=["POST"]) async def generate_text(request): data = request.json messages = [] messages.append({'role': 'system', 'content': "我希望你扮演一个英语翻译机。我提交汉字你帮我翻译成英文"}) messages.append({'role': 'user', 'content': data["context"]}) response = openai.ChatCompletion.create( model='gpt-3.5-turbo', messages=messages, ) print(messages) ai_response = response.

【swing】关闭,最大化按钮禁用

以下是使用Swing编写一个窗口的示例,其中窗口的最大化和关闭按钮被禁用,并在菜单栏上实现了关闭功能: package com.jcli.exit; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** 以下是使用Swing编写一个窗口的示例,其中窗口的最大化和关闭按钮被禁用,并在菜单栏上实现了关闭功能: */ public class MainWindow extends JFrame { public MainWindow() { initialize(); } private void initialize() { setTitle("My Window"); setSize(400, 300); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 禁用默认的关闭操作 setResizable(false);//不可放大 // 创建菜单栏 JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); // 创建菜单 JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); // 创建菜单项 JMenuItem exitMenuItem = new JMenuItem("Exit"); fileMenu.add(exitMenuItem); // 为菜单项添加事件监听器 exitMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 执行关闭操作 closeWindow(); } }); } private void closeWindow() { int option = JOptionPane.

ALtera DE2开发板烧录过程

1.ALtera DE2开发板 2.引脚文件 链接:https://pan.baidu.com/s/1fuGBxPXxAyNtJbwBFW4v7g 提取码:ghbl 3.quartus建立原型图 4.绑定引脚 5.烧录 第一次使用需要自行安装驱动 6.成功烧录

前端页面用户选择静态资源布置的图片,想拿url却拿到base64编码?

问题的原因; 简单一句话,图片太小了,低于webpack的limit设置的大小,就会自动转换为BASE64,内嵌到页面上,超过limit的才会单独打包为文件的. 如果确保代码中没有对图片进行转换为 Base64 编码的操作,而图片仍然以 Base64 编码的形式加载,那么很可能是在 webpack 的配置中使用了 url-loader 或 file-loader 对图片进行处理。这两个 loader 在对图片进行处理时,会将小于配置文件中指定大小的图片自动转换为 Base64 编码的形式内嵌到 HTML 或 CSS 文件中,大于配置文件中指定大小的图片则会被打包为单独的文件。 最直接的方法就是修改webpack,当然最简单的方法也可以处理图片大小,让他超过limit即可。 因此,可以检查一下webpack 配置文件中的 url-loader 或 file-loader 的配置项,将图片加载方式从 Base64 编码改为通过 URL 加载。其中,主要涉及到以下配置项: limit:指定小于该大小的图片会被转换为 Base64 编码的形式。将该值设置为 Infinity 可以避免图片被转换为 Base64 编码。fallback:指定生成的文件的 URL 路径。设为 file-loader,则会将图片打包为单独的文件,并生成相应的 URL 路径。 例如,以下是一份简化的 webpack 配置文件,用来将所有图片打包为单独的文件: module.exports = { // ... module: { rules: [{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [{ loader: 'file-loader', options: { name: 'img/[name].[hash:8].[ext]' } }] }] } }; 可以将 file-loader 替换为其他相关的 loader,例如 url-loader。

Python入门网络爬虫之精华版,赶快收藏

相关文件 关注小编,私信小编领取哟! 当然别忘了一件三连哟~~ 公众号:Python日志 前言 Python学习网络爬虫主要分3个大的版块:抓取,分析,存储 另外,比较常用的爬虫框架Scrapy,这里最后也详细介绍一下。 举例子 当我们在浏览器中输入一个url后回车,后台会发生什么? 简单来说这段过程发生了以下四个步骤: 查找域名对应的IP地址。向IP对应的服务器发送请求。服务器响应请求,发回网页内容。浏览器解析网页内容。 网络爬虫要做的,简单来说,就是实现浏览器的功能。通过指定url,直接返回给用户所需要的数据,而不需要一步步人工去操纵浏览器获取。 抓取 这一步,你要明确要得到的内容是什么?是HTML源码,还是Json格式的字符串等。 1. 最基本的抓取 抓取大多数情况属于get请求,即直接从对方服务器上获取数据。 首先,Python中自带urllib及urllib2这两个模块,基本上能满足一般的页面抓取。另外,requests也是非常有用的包,与此类似的,还有httplib2等等。 Requests: import requests response = requests.get(url) content = requests.get(url).content print "response headers:", response.headers print "content:", content Urllib2: import urllib2 response = urllib2.urlopen(url) content = urllib2.urlopen(url).read() print "response headers:", response.headers print "content:", content Httplib2: import httplib2 http = httplib2.Http() response_headers, content = http.request(url, 'GET') print "response headers:", response_headers print "content:", content 此外,对于带有查询字段的url,get请求一般会将来请求的数据附在url之后,以?分割url和传输数据,多个参数用&连接。

TensorFlow 实现车牌识别

文章目录 1:生成训练数据集2:数据读取3:构建神经网络模型4:开始训练模型5:测试模型准确度 1:生成训练数据集 #pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple #pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple import PIL from PIL import ImageFont from PIL import Image from PIL import ImageDraw import cv2; import numpy as np; import os; from math import * import matplotlib.pyplot as plt index = {"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9, "苏": 10, "浙": 11, "

图像数据处理

文章目录 1:TFRecords1-1 将MNIST数据集转换成TFRecord格式1-2 读取TFRecord文件中的数据 2:图像数据的预处理2-1 处理图像编码2-2 调整图像大小2-3 剪裁和填充2-4 按比例剪裁2-5 图像翻转2-6 图像亮度调整2-7 图像对比度调整2-8 图像色相调整2-9 图像饱和度调整2-10 标注框调整(随机图像截取)实例 3:多线程输入数据处理框架3-1 队列与多线程3-2 通过tf.Coordinator实现多线程协同3-3 管理多线程队列3-4 输入文件队列1643-5 通过tf.train.match_filenames_once()函数和tf.train.string_input_producer()函数来操作文件3-6 组合训练数据 4:将数据输入模型 1:TFRecords 1-1 将MNIST数据集转换成TFRecord格式 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import numpy as np # 将输入转化成TFRecord格式并保存 # 定义函数转化变量类型。 def _int64_feature(value): return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) def _bytes_feature(value): return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) # 读取mnist数据。 mnist = input_data.read_data_sets(r"./mnist", one_hot=True) images = mnist.train.images labels = mnist.train.labels pixels = images.shape[1] num_examples = mnist.train.num_examples # 输出TFRecord文件的地址。 filename = "

java线程池ThreadPoolExecutor使用

文章目录 一、简介1. 背景2. Executor接口介绍 二、使用Executors工厂创建线程池1. 简介2. 使用newCachedThreadPool()方法创建无界线程池3. 验证newCachedThreadPool()方法创建的线程池和线程复用特性4. 使用newCachedThreadPool(ThreadFactory)定制线程工厂5. 使用newCachedThreadPool()方法创建无界线程池的缺点6. 使用newFixedThreadPool(int)方法创建有界线程池7. 使用newSingleThreadExecutor()方法创建单一线程池 三、ThreadPoolExecutor使用(重点)1. 简介2. 队列LinkedBlockingQueue、ArrayBlockingQueue和SynchronousQueue的基本使用3. ThreadPoolExecutor的构造方法详解(1)简介(2)使用阻塞队列(3)验证1-1(4)验证1-2(5)验证1-3(6)验证2-1(7)验证2-2(8)验证2-3(9)验证3-1(10)验证3-2(11)验证3-3(12)验证3-4(13)验证参数keepAliveTime非0的实验 4. 方法shutdown()和shutdownNow()5. 其它方法(1) isShutdown()方法(2) 方法isTerminating()和isTerminated()(3) 方法awaitTermination(long timeout,TimeUnit unit)(4) 使用ThreadFactory+UncaughtExceptionHandler处理异常(5)方法set/getRejectedExceptionHandler()(5)方法allowsCoreThreadOut()和allowCoreThreadTimeOut(boolean value)(6)方法prestartCoreThread()和prestartAllcoreThreads()(7)方法getCompletedTaskCount() 6. 线程池ThreadPoolExecutor的拒绝策略(1)AbortPolicy策略(2)CallerRunsPolicy策略(3)DiscardOldestPolicy策略(3)DiscardPolicy策略 7. 方法afterExcute()和beforeExcute()8. 方法Remove(Runnable)使用9. 常见的get方法以及使用 一、简介 1. 背景 在开发服务端软件项目时,软件经常需要处理执行时间很短而数目巨大的请求,如果为每一个请求创建一个新的线程,则会导致性能上的瓶颈。因为JVM需要频繁的处理线程对象的创建与销毁,如果请求的执行时间很短,则有可能花在创建和销毁线程对象上的时间大于真正执行的时间,所以系统的性能会大幅度降低。JDK 5以上版本提供了对线程池的支持,主要用于支持高并发的访问处理,并且复用线程对象。线程池的核心原理是创建一个“线程池”,在池中对线程对象进行管理,包括创建与销毁,使用池时只需执行具体的任务即可,线程对象的处理都在池中封装了。线程池ThreadPoolExecutor实现类Executor接口,该接口是学习线程池的重点,因为掌握了该接口中的方法也就大致掌握了ThreadPoolExecutor类的主要功能了。 2. Executor接口介绍 在介绍线程池之前,要先了解一下接口java.util.concurrent.Executor,与线程池有关的大部分类都要实现这个接口。源码如下: public interface Executor { /**在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由实现自行 Executor 决定。 参数: command – 可运行的任务 抛出: RejectedExecutionException – 如果无法接受此任务执行 NullPointerException – 如果命令为空 **/ void execute(Runnable command); } ExecutorService 是 Java 中的一个接口,用于管理和控制任务的执行。它继承了 Executor 接口,并扩展了一些额外的方法,提供了更丰富的功能来操作任务执行。ExecutorService 的主要目的是将任务的提交和执行解耦,使得任务的提交者可以专注于任务的创建,而不需要关心任务的具体执行细节。它提供了一种线程池的方式来执行任务,以提高效率并控制资源的使用。通过 ExecutorService,可以将任务提交给线程池进行执行,并且可以获取任务执行的结果。它还提供了一些管理和监控线程池的方法,如关闭线程池、等待任务执行完成、判断线程池是否关闭等,但Executor是接口,并不能直接使用,所以还需要实现类,下图就是继承关系图:

Redis分片集群搭建及其原理

Redis分片集群搭建及其原理 1.Redis分片集群1.1.搭建分片集群1.2.准备实例和配置1.3.启动1.4.创建集群1.5.测试 2.散列插槽原理2.1.插槽原理2.2.小结 3.集群伸缩3.1.需求分析3.2.创建新的redis实例3.3.添加新节点到redis3.4.转移插槽 4.故障转移4.1.自动故障转移4.2.手动故障转移 5.RedisTemplate访问分片集群 1.Redis分片集群 1.1.搭建分片集群 主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决: 海量数据存储问题 高并发写的问题 使用分片集群可以解决上述问题,如图: 分片集群特征: 集群中有多个master,每个master保存不同数据 每个master都可以有多个slave节点 master之间通过ping监测彼此健康状态 客户端请求可以访问集群任意节点,最终都会被转发到正确节点 分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下: 这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下: IPPORT角色192.168.150.1017001master192.168.150.1017002master192.168.150.1017003master192.168.150.1018001slave192.168.150.1018002slave192.168.150.1018003slave 1.2.准备实例和配置 删除之前的7001、7002、7003这几个目录,重新创建出7001、7002、7003、8001、8002、8003目录: # 进入/tmp目录 cd /tmp # 删除旧的,避免配置干扰 rm -rf 7001 7002 7003 # 创建目录 mkdir 7001 7002 7003 8001 8002 8003 在/tmp下准备一个新的redis.conf文件,内容如下: port 6379 # 开启集群功能 cluster-enabled yes # 集群的配置文件名称,不需要我们创建,由redis自己维护 cluster-config-file /tmp/6379/nodes.conf # 节点心跳失败的超时时间 cluster-node-timeout 5000 # 持久化文件存放目录 dir /tmp/6379 # 绑定地址 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 192.

表格树 element el-table

<el-table row-key="id" :data="tableData" style="width: 940px" :show-header="false" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"> <el-table-column prop="name" width="600px"> </el-table-column> <el-table-column align="right"> <template> <el-button type="primary" size="small" @click="handleDelete()" plain>做题</el-button> </template> </el-table-column> </el-table> tableData: [{ id: 1, name: '建设工程项目的组织与管理', children: [{ id: 1-1, name: '1Z201000建设工程项目的组织与管理', }, { id: 1-2, name: '1Z201000建设工程项目的组织与管理', }], }, { id: 2, name: '1Z201000建设工程项目的组织与管理', children: [{ id: 2-1, name: '1Z201000建设工程项目的组织与管理', }, { id: 2-2, name: '1Z201000建设工程项目的组织与管理', }], } ], css // 树形结构 //有子节点 且未展开 .

【Selenium & Other】使用quit()无法关闭窗口 & 一键杀死进程

前言 有位读者留言,遇到了一件两难全的事儿。在关闭Python使用os模块执行cmd命令调用的chromedriver驱动打开的chrome浏览器时,有以下问题~ 使用driver.quit()退出浏览器,chromedriver.exe进程退出,关闭没有窗口使用driver.close()退出浏览器,chromedriver.exe进程没有退出,窗口关闭 但是咱们这里全都要,下面就来解决它,顺便说一下关于杀死进程的事儿~ 文章链接在这: 标题链接【Selenium】Selenium绕过检测 & 隐藏特征【Selenium】Selenium绕过检测 & 隐藏特征 问题在这: 解决方法如下: 先关闭窗口,再杀掉 chromedriver.exe 进程。 driver.close() driver.quit() 全文完~🎈🎈 下面且再吧啦一下吧🏹🏹 问题复现 这份代码贯穿全文,将用于多次示例。 执行以下代码,详情看动图 执行以下代码,会启动一个名为 chromedriver.exe的进程,通过任务管理器 可看到 # -*- coding: utf-8 -*- # Name: hide_features.py # Author: 小菜 # Date: 2022/8/29 15:43 # Description: import os from selenium import webdriver from selenium.webdriver.chrome.options import Options if __name__ == '__main__': os.system(r'start chrome --remote-debugging-port=9527 --user-data-dir="F:\selenium"') options = Options() options.add_experimental_option("debuggerAddress", "127.0.0.1:9527") driver = webdriver.Chrome(options=options) driver.get('https://bot.sannysoft.com/') # driver.

svc.fit(X=, y=, sample_weight=)理解这句代码

fit的过程就是在将分类器拟合的过程 拟合和学习,训练是不是同一概念 拟合、训练和学习都可以被视为模型通过数据获取知识、调整自身以适应数据模式的过程。这些过程都涉及使用优化算法、损失函数和梯度下降等技术,以最小化预测误差并提高模型的预测能力。 尽管可以将这些术语视为同一概念,但有时也可以在特定上下文中将它们区分开来,以强调不同的方面或阶段。例如,拟合可能更强调将模型的输出与已知数据对齐的过程,训练可能更强调通过迭代优化来调整模型参数的过程,而学习可能更强调模型从数据中提取知识和模式的过程。 综上所述,拟合、训练和学习可以被视为相同的概念,但在特定的上下文中也可以从不同的角度加以区分和理解。

UFT软件的安装与注意事项

安装包下载 UFT软件的安装包网上也有许多,这里我分享下我使用的--->UFT安装包 下载完成解压后进行安装。 要注意关闭杀毒软件,否则安装过程中某些组件可能会安装不上。 部分电脑在安装过程中出现以下提示,可以点击确定 然后我们查看桌面上会出现两个图标 上面的就是我们用的UFT,下面的用来生成运行结果报告。 解决许可证问题 首次运行UFT会让我们安装许可证,我们点击继续会有30天的试用期。那么当时间到了之后怎么办呢,如下图。 我们首先到C盘的C:\ProgramData路径下找到SafeNet Sentinel这个文件夹,然后把它删掉。 之后在到UFT的安装目录的bin文件夹下,找到instdemo.exe文件 之后我们再次运行UFT就会看到试用时间重新变回30天了。 简单操作: 我们运行后会让我们选择插件,根据需要选择就行。 新建测试如下 小tips: 当我们测试前,可以配置一下测试结果的导出,便于查看--->测试结果的导出方法在这个博客里面 运行过程中出现分段截断怎么办---->分段截断的解决方法在这个博客里面

开发ChatGPT插件-入门

探索ChatGPT,学习开发一款插件,成为先锋者,一同成长。加入「阿杰与AI」公众号,关注AI发展趋势,等待AI机会出现。 1.如何访问插件?2.开发ChatGPT插件-介绍3.开发ChatGPT插件-入门4.开发ChatGPT插件-认证5.开发ChatGPT插件-示例插件6.开发ChatGPT插件-审核7.开发ChatGPT插件-线上插件及常见问题 创建一个插件需要3个步骤: 构建一个API使用OpenAPI的yaml或JSON格式对API进行文档化创建一个JSON清单文件,用于定义插件的相关元数据 接下来的内容将重点介绍通过定义OpenAPI规范和清单文件来创建一个待办事项列表插件。 插件清单 每个插件都需要一个名为ai-plugin.json的文件,并且该文件需要托管在API的域名下。例如,一个名为example.com的公司会将插件的JSON文件通过https://example.com域名进行访问,因为这是他们API托管的位置.当您通过ChatGPT UI安装插件时,后台会在/.well-known/ai-plugin.json位置查找文件。在您的域名上,必须有一个名为/.well-known的文件夹,以便ChatGPT能够连接到您的插件。如果找不到文件,插件将无法安装。对于本地开发,您可以使用HTTP,但如果指向远程服务器,则必须使用HTTPS。 所需的ai-plugin.json文件的最小定义如下所示: { "schema_version": "v1", "name_for_human": "TODO Plugin", "name_for_model": "todo", "description_for_human": "Plugin for managing a TODO list. You can add, remove and view your TODOs.", "description_for_model": "Plugin for managing a TODO list. You can add, remove and view your TODOs.", "auth": { "type": "none" }, "api": { "type": "openapi", "url": "http://localhost:3333/openapi.yaml", "is_user_authenticated": false }, "logo_url": "http://localhost:3333/logo.png", "contact_email": "support@example.com", "legal_info_url": "http://www.example.com/legal" } 如果您想查看插件文件的所有可能选项,可以参考下面的定义。在命名插件时,请遵循OpenAI的品牌指南,不符合这些指南的插件将无法获得插件商店的批准。

学习open62541 --- [76] 使用智能指针处理内存释放问题

在使用监测项时,一般都会加一个context,然后在回调函数里使用这个context,这就需要保证context的内存空间在执行回调函数时是有效的。往往有以下三种方法: 使用静态内存空间:使用static创建静态变量,然后把变量地址当做context,缺点是一个静态变量只能用于一个监测项,函数无法重用(重用会造成多个监测项使用同一个静态变量)使用局部内存空间:保证局部变量一直有效就行,例如局部变量定义在main函数里,因为main函数一直在栈上,所以这个局部变量会一直有效。这个只能用于简单项目。使用动态内存:在创建监测项时直接动态分配内存,比较简单,就是释放内存比较费劲 一般来说,都是使用第三个方法。本文先举例讲解第三个方法,最后讲述如何使用智能指针去解决释放问题。 一 例子 下面是个简单的监测项例子,server端添加一个变量,然后创建监测项去监测该变量,再添加一个定时任务去每隔2s把该变量的值加1,从而可以触发监测的回调函数, // server.cpp #include <memory> #include <signal.h> #include <stdlib.h> #include <unistd.h> #include "open62541.h" UA_Boolean running = true; void stopHandler(int sign) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c"); running = false; } UA_UInt32 monid = 0; UA_NodeId addTheAnswerVariable(UA_Server *server) { /* Define the attribute of the myInteger variable node */ UA_VariableAttributes attr = UA_VariableAttributes_default; UA_Int32 myInteger = 1; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); attr.description = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"the answer"); attr.displayName = UA_LOCALIZEDTEXT((char*)"

2023OD机试---特殊赛制投篮大赛

特殊赛制投篮大赛 以下内容由题目介绍,输入和输出,用例介绍,代码实现4部分组成。 建议理解解题过程,请勿完全死记硬背代码,不断练习,才能提高编码能力。 题目介绍 【查找单入口空闲区域】 时间限制:1s空间限制:256MB限定语言:不限 题目描述: 给定一个xn的矩阵,由若干字符X’和’O’构成,X表示该处已被占据,'O表示该处空闲,请找到最大的单入 口空闲区域。 解释: 空闲区域是由连通的’O’组成的区域,位于边界的O’可以构成入口,单入口空闲区域即有且只有一个位于边界的O’作 为入口的由连通的O组成的区域。 如果两个元素在水平或垂直方向相邻,则称它们是“连通”的。 输入和输出 【输入描述】 第一行输入为两个数字,第一个数字为行数m,第二个数字列数n,两个数字以空格分隔,1<=m,n<=200,剩余各行为矩阵各行元素,元素为X或’O’,各元素间以空格分隔。 【输出描述】 若有唯一符合要求的最大单入口空闲区域,输出三个数字: 第一个数字为入口行坐标(范围为0~行数-1), 第二个数字为入口列坐标(范围为0~列数-1), 第三个数字为区域大小,三个数字以空格分隔; 若有多个符合要求的最大单入口空闲区域,输出一个数字,代表区域的大小; 若没有,输出NUL。 用例介绍 示例1 【输入】 4 4 X X X X X O O X X O O X X O X X 【输出】 3 1 5 【说明】 存在最大单入口区域,入口行坐标3,列坐标1,区域大小5 示例2 【输入】 4 5 X X X X X O O O O X X O O O X X O X X O 【输出】

Java常用工具之StringUtils类

目录 一、字符串判空二、分隔字符串三、判断是否为纯数字四、将集合拼接成字符串五、其他方法 字符串(String)在我们的日常工作中,用得非常非常非常多。 在我们的代码中经常需要对字符串判空,截取字符串、转换大小写、分隔字符串、比较字符串、去掉多余空格、拼接字符串、使用正则表达式等等。 如果只用 String 类提供的那些方法,我们需要手写大量的额外代码,不然容易出现各种异常。 现在有个好消息是:org.apache.commons.lang3包下的StringUtils工具类,给我们提供了非常丰富的选择。 Maven 坐标: <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> StringUtils 提供了非常多实用的方法,大概有下图的四页到五页,我只截了两页,实在是太多了。 接下来,我们来拿一些常用的方法举例说明。 一、字符串判空 其实空字符串,不只是 null 一种,还有"“,” ","null"等等,多种情况。 StringUtils 给我们提供了多个判空的静态方法,例如: String str1 = null; String str2 = ""; String str3 = " "; String str4 = "abc"; System.out.println(StringUtils.isEmpty(str1)); System.out.println(StringUtils.isEmpty(str2)); System.out.println(StringUtils.isEmpty(str3)); System.out.println(StringUtils.isEmpty(str4)); System.out.println("====="); System.out.println(StringUtils.isNotEmpty(str1)); System.out.println(StringUtils.isNotEmpty(str2)); System.out.println(StringUtils.isNotEmpty(str3)); System.out.println(StringUtils.isNotEmpty(str4)); System.out.println("====="); System.out.println(StringUtils.isBlank(str1)); System.out.println(StringUtils.isBlank(str2)); System.out.println(StringUtils.isBlank(str3)); System.out.println(StringUtils.isBlank(str4)); System.out.println("====="); System.out.println(StringUtils.isNotBlank(str1)); System.out.println(StringUtils.isNotBlank(str2)); System.out.println(StringUtils.isNotBlank(str3)); System.out.println(StringUtils.isNotBlank(str4)); 执行结果: true true false false ===== false false true true ===== true true true false ===== false false false true 示例中的:isEmpty、isNotEmpty、isBlank和isNotBlank,这 4 个判空方法你们可以根据实际情况使用。

监听Redis 缓存过期(Key 失效)事件

监听Redis 缓存过期(Key 失效)事件 1.修改config配置 因为事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 所以需要开启 redis 的事件监听与发布 打开 notify-keyspace-events Ex 的注释,开启过期通知功能 2.重启redis , 即可测试失效事件的触发, 监听获取的值为 key 3.进入redis-client docker exec -it 容器id redis-cli #调用客户端 4.进入监听 PSUBSCRIBE __keyevent@*__:expired 5.再打开一个 redis-client,发送过期数据 setex test 2 2 6.返回之前的 client,监听到过期事件 redis 环境配置完毕; springboot集成 yml配置 spring: redis: host: xx.xxx.xx.xx password: xxxx port: 6379 database: 6 配置 redis 远程监听配置: import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.RedisMessageListenerContainer; /** * Description: redis 远程监听 * User: liw * Date: 2023-05-20 */ @Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer listenerContainer(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer(); listenerContainer.

超火的chartGPT到底是什么?没有账号我能使用吗

什么是OpenAI? OpenAl是一家人工智能研究公司,成立于2015年,总部位于美国加利福尼亚州旧金山。公司的目标是建立一种通用人工智能技术,并将其让普通人能够轻松使用。OpenAl的研究领域包括机器学习、自然语言处理和强化学习等。其中,GPT-3是OpenAl开发的一种大型语言模型,可以进行自然语言生成、翻译和问答等任务。 什么是ChartGPT? ChatGPT是OpenAl开发的一种基于GPT-3模型的语言生成系统。它可以生成高质量的人类文本,并具有自然语言理解和对话管理能力。ChatGPT可用于自动回复、对话机器人、问答系统和其他自然语言处理应用等。它使用了大量的自然语言文本数据来训练,并可以通过 微调来适应特定场景。ChatGPT使用起来相对简单,可以通过API接口或者其他工具使用。 ChartGPT如何收费? ChatGPT是OpenAl提供的一种付费服务,客户可以通过API访问模型型。计费标准一般是 按照请求数量和使用时长进行收费。客户可以根据自己的的需求购买不同的套餐,以获得相应 的请求配额和使用时长。另外,OpenAl也提供了免费配额,用户可以免费试用模型。总 之,如果你想使用chatgpt,那么就需要付费,具体的费用需要去OpenAl官网或者联系OpenAl客服来确定。 没有账号能使用吗? 中国国内使用ChatGPT,可以通过OpenAI提供的API接口或者直接下载源代码进行部署。使用API接口的方法是在OpenAI网站注册账号,然后获取API Key,再使用你喜欢的编程语言发送请求到API服务器。如果选择部署源代码,你需要有一台服务器,并安装好相关的软件环境,按照OpenAI提供的指导部署模型。 如果你想使用ChatGPT,我可以免费给你尝试哈~加我耗油哦~ 知道你对python感兴趣,所以给你准备了下面的资料~ 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以点击链接免费领取或者滑到最后扫描二v码保证100%免费】 python学习资源免费分享,保证100%免费!!! 需要的话可以点击这里👉Python学习路线(2023修正版)附涉及资料 (安全链接,放心点击) 文末有福利领取哦~ 一、Python所有方向的学习路线 Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。​​​​ 二、Python必备开发工具 ​​​​ 三、精品Python学习书籍 当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。 四、Python视频合集 观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 ​​​​ ​​​​ 五、实战案例 光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。 ​​​​ 六、Python练习题 检查学习结果。 ​​​​ 七、面试资料 我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。 ​​​​ ​​​​ 👉这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方CSDN官方认证二维码或者点击链接免费领取【保证100%免费】 Python学习路线(2023修正版)附涉及资料《Python学习资料》,已经打包好了,自取【ps:需要领取的资料(请备注清楚,查找与发送给你)】。因链接常https://mp.weixin.qq.com/s/UVxw0daFCgAMFhz9cfrjAQ

C++中的std::

std:: 是个空间标识符;C++标准库中的函数/对象都是在命名空间std中定义的 ,所以每当我们要使用标准函数库中的函数/对象时,都要使用std来限定;对象cout是标准函数库所提供的对象,而标准库在名字空间中被指定为std,所以在使用cout的时候要加上std:: 示例如下: #include<iostream.h> int main(){ std::cout<<"Hello world"<<std::endl; return 0; } 下面没有在cout和endl的前面加上std::就出错了 错误 C2065 “endl”: 未声明的标识符 C2065 “cout”: 未声明的标识符 #include<iostream> int main() { cout << "Hello world" << endl; } 而使用非标准库头文件<iostream.h>可不用写,iostream是C++的头文件,iostream.h是C的头文件,即标准的C++头文件没有.h扩展名) #include<iostream.h> int main() { cout << "Hello world" << endl; } 直接在main函数下面输入 using std::cout; using std::endl; 这种方法也可以 或者直接在头文件下面加上using namespace std;即 #include <iostream> using namespace std; int main() { int n; cin >> n; }