flask部署钉钉机器人和企业微信机器人

引言

创建机器人,目的是通过@机器人的方式,提出用户的问题,得到想要的回答

钉钉机器人

  • 首先我们需要获取钉钉的企业内部开发者权限
  • 然后我们进入钉钉开放平台,登陆后,选择应用开发->机器人->创建应用,我创建了一个叫做chat的机器人
    在这里插入图片描述
  • 点击进入机器人,在应用信息中有你的AgentID,AppKey和AppSecret,在后面使用中只有AppSecret是有用的。在开发管理处,我们需要配置服务器出口IP和消息接收地址,服务器出口IP填写服务器的IP即可,消息接收地址为外网端口,就是部署应用使用的端口,例如falsk端口
    在这里插入图片描述
  • 完成之后,我们就可以写这个机器人的回调程序了,我在写回调的时候,发现钉钉机器人接收消息必须在主页面,不能在子页面,主页面指在app.route中的地址为"/“,子页面指”/dingdingrobot",这里我使用的消息是通过openai的chatgpt构建回复并输出
from flask import Flask, request, jsonify
import base64
import openai
app = Flask(__name__)
openai.api_key = '你的openai密钥'
@app.route("/", methods=["POST", 'GET'])
def get_data():print('进来了')return dingRobot(request)
def dingRobot(request):try:# 第一步验证:是否是post请求if request.method == "POST":# print(request.headers)# 签名验证 获取headers中的Timestamp和Signtimestamp = request.headers.get('Timestamp')sign = request.headers.get('Sign')# 第二步验证:签名是否有效if check_sig(timestamp) == sign:# 获取数据 打印出来看看text_info = json.loads(str(request.data, 'utf-8'))handle_info(text_info)print('验证通过')return str(text_info)print('验证不通过')return str(timestamp)print('有get请求')return str(request.headers)except Exception as e:webhook_url = text_info['sessionWebhook']senderid = text_info['senderId']title = Nonetext = str(e)send_md_msg(senderid, title, text, webhook_url)return str(request.headers)
# 处理自动回复消息
def handle_info(req_data):# 解析用户发送消息 通讯webhook_url text_info = req_data['text']['content'].strip()maxlen = 2048if '生成长度' in text_info:res = re.split('生成长度', text_info)text_info = res[0].strip()maxlen = int(res[1].strip())webhook_url = req_data['sessionWebhook']senderid = req_data['senderId']# print('***************text_info:', text_info)# if判断用户消息触发的关键词,然后返回对应内容# python3.10 以上还可以用 switch case...title = Noneresponse = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": text_info}])text = response['choices'][0]['message']['content'].strip()print(text)# 调用函数,发送markdown消息send_md_msg(senderid, title, text, webhook_url)
# 发送markdown消息
def send_md_msg(userid, title, message, webhook_url):'''userid: @用户 钉钉idtitle : 消息标题message: 消息主体内容webhook_url: 通讯url'''# data = {#     "msgtype": "markdown",#     "markdown": {#         "title":title,#         "text": message#     },#     '''#     "msgtype": "text",#     "text": {#         "content": message#     },#     '''#     "at": {#         "atUserIds": [#           userid#       ],#     }# }data = {"at": {"atUserIds": [userid],"isAtAll": False},"text": {"content": message},"msgtype": "text"}# 利用requests发送post请求req = requests.post(webhook_url, json=data)
# 消息数字签名计算核对
def check_sig(timestamp):app_secret = '你的AppSecret'app_secret_enc = app_secret.encode('utf-8')string_to_sign = '{}\n{}'.format(timestamp, app_secret)string_to_sign_enc = string_to_sign.encode('utf-8')hmac_code = hmac.new(app_secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()sign = base64.b64encode(hmac_code).decode('utf-8')return sign
if __name__ == '__main__':app.run(host='0.0.0.0', port=8001)
  • 在版本管理与发布界面中,我们就可以调试钉钉机器人了
    在这里插入图片描述
  • 效果
    在这里插入图片描述

企业微信机器人

  • 企业微信机器人需要开发者为企业微信的管理者,在拥有管理者授权之后,我们可以添加小程序机器人
    在这里插入图片描述
  • 点进去之后,我们可以看到AgentID和Secret
    在这里插入图片描述
  • 和钉钉机器人一样,我们需要配置企业可信任IP,填写服务器的IP
    在这里插入图片描述
  • 然后开始设置回调函数,下面代码为验证签名的代码,保存到WXBizMsgCrypt.py
#!/usr/bin/env python
# -*- encoding:utf-8 -*-""" 对企业微信发送给企业后台的消息加解密示例代码.
@copyright: Copyright (c) 1998-2014 Tencent Inc.
"""
# ------------------------------------------------------------------------
import logging
import base64
import random
import hashlib
import time
import struct
from Crypto.Cipher import AES
import xml.etree.cElementTree as ET
import socketimport ierror"""
关于Crypto.Cipher模块,ImportError: No module named 'Crypto'解决方案
请到官方网站 https://www.dlitz.net/software/pycrypto/ 下载pycrypto。
下载后,按照README中的“Installation”小节的提示进行pycrypto安装。
"""class FormatException(Exception):passdef throw_exception(message, exception_class=FormatException):"""my define raise exception function"""raise exception_class(message)class SHA1:"""计算企业微信的消息签名接口"""def getSHA1(self, token, timestamp, nonce, encrypt):"""用SHA1算法生成安全签名@param token:  票据@param timestamp: 时间戳@param encrypt: 密文@param nonce: 随机字符串@return: 安全签名"""try:sortlist = [token, timestamp, nonce, encrypt]sortlist.sort()sha = hashlib.sha1()sha.update("".join(sortlist).encode())return ierror.WXBizMsgCrypt_OK, sha.hexdigest()except Exception as e:logger = logging.getLogger()logger.error(e)return ierror.WXBizMsgCrypt_ComputeSignature_Error, Noneclass XMLParse:"""提供提取消息格式中的密文及生成回复消息格式的接口"""# xml消息模板AES_TEXT_RESPONSE_TEMPLATE = """<xml>
<Encrypt><![CDATA[%(msg_encrypt)s]]></Encrypt>
<MsgSignature><![CDATA[%(msg_signaturet)s]]></MsgSignature>
<TimeStamp>%(timestamp)s</TimeStamp>
<Nonce><![CDATA[%(nonce)s]]></Nonce>
</xml>"""def extract(self, xmltext):"""提取出xml数据包中的加密消息@param xmltext: 待提取的xml字符串@return: 提取出的加密消息字符串"""try:xml_tree = ET.fromstring(xmltext)encrypt = xml_tree.find("Encrypt")return ierror.WXBizMsgCrypt_OK, encrypt.textexcept Exception as e:logger = logging.getLogger()logger.error(e)return ierror.WXBizMsgCrypt_ParseXml_Error, Nonedef generate(self, encrypt, signature, timestamp, nonce):"""生成xml消息@param encrypt: 加密后的消息密文@param signature: 安全签名@param timestamp: 时间戳@param nonce: 随机字符串@return: 生成的xml字符串"""resp_dict = {'msg_encrypt': encrypt,'msg_signaturet': signature,'timestamp': timestamp,'nonce': nonce,}resp_xml = self.AES_TEXT_RESPONSE_TEMPLATE % resp_dictreturn resp_xmlclass PKCS7Encoder():"""提供基于PKCS7算法的加解密接口"""block_size = 32def encode(self, text):""" 对需要加密的明文进行填充补位@param text: 需要进行填充补位操作的明文@return: 补齐明文字符串"""text_length = len(text)# 计算需要填充的位数amount_to_pad = self.block_size - (text_length % self.block_size)if amount_to_pad == 0:amount_to_pad = self.block_size# 获得补位所用的字符pad = chr(amount_to_pad)return text + (pad * amount_to_pad).encode()def decode(self, decrypted):"""删除解密后明文的补位字符@param decrypted: 解密后的明文@return: 删除补位字符后的明文"""pad = ord(decrypted[-1])if pad < 1 or pad > 32:pad = 0return decrypted[:-pad]class Prpcrypt(object):"""提供接收和推送给企业微信消息的加解密接口"""def __init__(self, key):# self.key = base64.b64decode(key+"=")self.key = key# 设置加解密模式为AES的CBC模式self.mode = AES.MODE_CBCdef encrypt(self, text, receiveid):"""对明文进行加密@param text: 需要加密的明文@return: 加密得到的字符串"""# 16位随机字符串添加到明文开头text = text.encode()text = self.get_random_str() + struct.pack("I", socket.htonl(len(text))) + text + receiveid.encode()# 使用自定义的填充方式对明文进行补位填充pkcs7 = PKCS7Encoder()text = pkcs7.encode(text)# 加密cryptor = AES.new(self.key, self.mode, self.key[:16])try:ciphertext = cryptor.encrypt(text)# 使用BASE64对加密后的字符串进行编码return ierror.WXBizMsgCrypt_OK, base64.b64encode(ciphertext)except Exception as e:logger = logging.getLogger()logger.error(e)return ierror.WXBizMsgCrypt_EncryptAES_Error, Nonedef decrypt(self, text, receiveid):"""对解密后的明文进行补位删除@param text: 密文@return: 删除填充补位后的明文"""try:cryptor = AES.new(self.key, self.mode, self.key[:16])# 使用BASE64对密文进行解码,然后AES-CBC解密plain_text = cryptor.decrypt(base64.b64decode(text))except Exception as e:logger = logging.getLogger()logger.error(e)return ierror.WXBizMsgCrypt_DecryptAES_Error, Nonetry:pad = plain_text[-1]# 去掉补位字符串# pkcs7 = PKCS7Encoder()# plain_text = pkcs7.encode(plain_text)# 去除16位随机字符串content = plain_text[16:-pad]xml_len = socket.ntohl(struct.unpack("I", content[: 4])[0])xml_content = content[4: xml_len + 4]from_receiveid = content[xml_len + 4:]except Exception as e:logger = logging.getLogger()logger.error(e)return ierror.WXBizMsgCrypt_IllegalBuffer, Noneif from_receiveid.decode('utf8') != receiveid:return ierror.WXBizMsgCrypt_ValidateCorpid_Error, Nonereturn 0, xml_contentdef get_random_str(self):""" 随机生成16位字符串@return: 16位字符串"""return str(random.randint(1000000000000000, 9999999999999999)).encode()class WXBizMsgCrypt(object):# 构造函数def __init__(self, sToken, sEncodingAESKey, sReceiveId):try:self.key = base64.b64decode(sEncodingAESKey + "=")assert len(self.key) == 32except:throw_exception("[error]: EncodingAESKey unvalid !", FormatException)# return ierror.WXBizMsgCrypt_IllegalAesKey,Noneself.m_sToken = sTokenself.m_sReceiveId = sReceiveId# 验证URL# @param sMsgSignature: 签名串,对应URL参数的msg_signature# @param sTimeStamp: 时间戳,对应URL参数的timestamp# @param sNonce: 随机串,对应URL参数的nonce# @param sEchoStr: 随机串,对应URL参数的echostr# @param sReplyEchoStr: 解密之后的echostr,当return返回0时有效# @return:成功0,失败返回对应的错误码def VerifyURL(self, sMsgSignature, sTimeStamp, sNonce, sEchoStr):sha1 = SHA1()ret, signature = sha1.getSHA1(self.m_sToken, sTimeStamp, sNonce, sEchoStr)if ret != 0:return ret, Noneif not signature == sMsgSignature:return ierror.WXBizMsgCrypt_ValidateSignature_Error, Nonepc = Prpcrypt(self.key)ret, sReplyEchoStr = pc.decrypt(sEchoStr, self.m_sReceiveId)return ret, sReplyEchoStrdef EncryptMsg(self, sReplyMsg, sNonce, timestamp=None):# 将企业回复用户的消息加密打包# @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串# @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp,如为None则自动用当前时间# @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce# sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,# return:成功0,sEncryptMsg,失败返回对应的错误码Nonepc = Prpcrypt(self.key)ret, encrypt = pc.encrypt(sReplyMsg, self.m_sReceiveId)encrypt = encrypt.decode('utf8')if ret != 0:return ret, Noneif timestamp is None:timestamp = str(int(time.time()))# 生成安全签名sha1 = SHA1()ret, signature = sha1.getSHA1(self.m_sToken, timestamp, sNonce, encrypt)if ret != 0:return ret, NonexmlParse = XMLParse()return ret, xmlParse.generate(encrypt, signature, timestamp, sNonce)def DecryptMsg(self, sPostData, sMsgSignature, sTimeStamp, sNonce):# 检验消息的真实性,并且获取解密后的明文# @param sMsgSignature: 签名串,对应URL参数的msg_signature# @param sTimeStamp: 时间戳,对应URL参数的timestamp# @param sNonce: 随机串,对应URL参数的nonce# @param sPostData: 密文,对应POST请求的数据#  xml_content: 解密后的原文,当return返回0时有效# @return: 成功0,失败返回对应的错误码# 验证安全签名xmlParse = XMLParse()ret, encrypt = xmlParse.extract(sPostData)if ret != 0:return ret, Nonesha1 = SHA1()ret, signature = sha1.getSHA1(self.m_sToken, sTimeStamp, sNonce, encrypt)if ret != 0:return ret, Noneif not signature == sMsgSignature:return ierror.WXBizMsgCrypt_ValidateSignature_Error, Nonepc = Prpcrypt(self.key)ret, xml_content = pc.decrypt(encrypt, self.m_sReceiveId)return ret, xml_content
  • 然后创建部署.py文件,微信机器人可以不在子界面收消息
from flask import Flask, request, jsonify
import base64
import openai
from WXBizMsgCrypt import WXBizMsgCrypt
import xml.etree.cElementTree as ET
app = Flask(__name__)
openai.api_key = '你的openai密钥'
@app.route("/wx", methods=["POST", "GET"])
def get_data():print('进来了')sToken = "3mGn6i6w"sEncodingAESKey = "T458mrywHPrJkDkkXJsUSAJCsutus7NMx5DPWUOSzFF"sCorpID = "wwe3b6de40ee9b0727"wxcpt=WXBizMsgCrypt(sToken,sEncodingAESKey,sCorpID)try:# 第一步验证:是否是post请求if request.method == "GET":# print(request.headers)# 签名验证 获取4种验证条件sVerifyMsgSig = request.args.get('msg_signature')sVerifyTimeStamp = request.args.get('timestamp')sVerifyNonce = request.args.get('nonce')sVerifyEchoStr = request.args.get('echostr')ret,sEchoStr=wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,sVerifyNonce,sVerifyEchoStr)return sEchoStrelse:sReqMsgSig = request.args.get('msg_signature')sReqTimeStamp = request.args.get('timestamp')sReqNonce = request.args.get('nonce')sReqData = request.dataret,sMsg=wxcpt.DecryptMsg( sReqData, sReqMsgSig, sReqTimeStamp, sReqNonce)if( ret!=0 ):print("ERR: DecryptMsg ret: " + str(ret))xml_tree = ET.fromstring(sMsg)content = xml_tree.find("Content").textmodel_output = get_model_response(content)sRespData = f"<xml><ToUserName>{sCorpID}</ToUserName><FromUserName>deploy</FromUserName><CreateTime>{sReqTimeStamp}</CreateTime><MsgType>text</MsgType><Content>{model_output}</Content><MsgId>{sReqNonce}</MsgId><AgentID>1000002</AgentID></xml>"ret,sEncryptMsg=wxcpt.EncryptMsg(sRespData, sReqNonce, sReqTimeStamp)if( ret!=0 ):print("ERR: EncryptMsg ret: " + str(ret))return sEncryptMsgreturn ''except Exception as e:sRespData = f"<xml><ToUserName>{sCorpID}</ToUserName><FromUserName>deploy</FromUserName><CreateTime>{sReqTimeStamp}</CreateTime><MsgType>text</MsgType><Content>{str()}</Content><MsgId>{sReqNonce}</MsgId><AgentID>1000002</AgentID></xml>"ret,sEncryptMsg=wxcpt.EncryptMsg(sRespData, sReqNonce, sReqTimeStamp)return sEncryptMsgprint(str(e))
def get_model_response(text, maxlen=2048):response = openai.Completion.create(model='text-davinci-003',prompt=text,temperature=0.7,max_tokens=maxlen,top_p=1.0,frequency_penalty=0.0,presence_penalty=0.0)text = response.choices[0].text.strip()return text
if __name__ == '__main__':app.run(host='0.0.0.0', port=8001)
  • 部署完成后,我们可以在企业微信工作台找到这个小程序,并进行聊天
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视觉大模型调研(Survey of Visual Foundation Model)

目录 A.写在前面 B.论文支撑与基础理论 1.大模型基本概念的诞生 2.大模型产业化落地的理论支撑 3.视觉模型架构的形成-Transformer到ViT再到MAE C.产业落地化现状 1.百度文心 UFO 2.0 整体概述 原理介绍 模型效果 应用场景与方案 2.华为 盘古CV视觉大模型 模型预训…

30亿参数,华为云发布全球最大预训练模型,开启工业化AI开发新模式

本文分享自华为云社区《HDC.Cloud 2021 | 华为云发布全球最大预训练模型&#xff0c;开启工业化AI开发新模式》&#xff0c;原文作者&#xff1a;技术火炬手 。 4月25日&#xff0c;华为云发布盘古系列超大规模预训练模型&#xff0c;包括30亿参数的全球最大视觉&#xff08;C…

AI大模型未来将走向何方?广泛应用成首要挑战

导读&#xff1a;如何让AI大模型被广泛应用起来&#xff1f; 目前在AI行业&#xff0c;大模型火到破圈。 今年11月初&#xff0c;华为云盘古大模型的机场广告在首都机场和深圳宝安机场亮相&#xff0c;主打“行业AI开发应用优选”的定位。11月18日&#xff0c;权威时政媒体中国…

千亿参数的盘古大模型

盘古系列AI大模型包括NLP大模型、CV大模型、多模态大模型、和科学计算大模型。具备超大神经网络&#xff0c;实际参数量超千亿&#xff1b;具备强大网络架构&#xff0c;实际综合性能比定制化模型提升10%&#xff1b;具备优秀泛化能力&#xff0c;全场景覆盖率提升10倍。 传统…

华为高级研究员谢凌曦:下一代AI将走向何方?盘古大模型探路之旅

摘要&#xff1a;为了更深入理解千亿参数的盘古大模型&#xff0c;华为云社区采访到了华为云EI盘古团队高级研究员谢凌曦。谢博士以非常通俗的方式为我们娓娓道来了盘古大模型研发的“前世今生”&#xff0c;以及它背后的艰难往事。 本文分享自华为云社区《华为高级研究员谢凌曦…

华为盘古大模型:能源领域的颠覆性突破

近日&#xff0c;华为盘古大模型在能源领域横空出世&#xff0c;引发了广泛关注和期待。作为一项具有颠覆性影响的技术创新&#xff0c;华为盘古大模型在能源行业中展现出巨大的潜力和前景。其优质的计算能力和智能优化算法&#xff0c;将为能源产业带来翻天覆地的变革。 盘古大…

【NLP】华为推出了全球最大的中文语言模型-盘古

作者&#xff1a;金雪锋链接&#xff1a;https://www.zhihu.com/question/456443707/answer/1856014437 这次HDC大会&#xff0c;华为联合鹏城发布了两个千亿的NLP大模型&#xff08;其中一个模型还和循环智能进行了合作&#xff09;&#xff0c;都是盘古命名的。 一个是4月25日…

快来试试!免费用上GPT-4 !!!

GPT-4 简介 GPT-4是OpenAI上个月推出的最新人工智能语言模型&#xff0c;它可以根据给定的文本或关键词生成各种类似于人类语言甚至超越人类语言的文本&#xff0c;例如文章、故事、诗歌、代码、对话等。 GPT-4拥有1750亿个参数&#xff0c;是目前最大的语言模型之一&#xf…

想找一些外文文献,有哪些靠谱的外文文献网站推荐?

论文写作是目前几乎每个专科生、本科生、研究生的必修课&#xff0c;保证毕业的同时也能够进行一定科研工作。论文写作是基于一定科研试验或社会调查的&#xff0c;但过程中文献检索能力同样不可或缺&#xff0c;能否真正的搞好科研&#xff0c;关键在于能否读懂前人的研究。对…

Get Offer —— 简历投递与加分细节

点赞后看,养成习惯 喜欢的话 可以点个关注哟 你们的点赞支持对博主们来说很重要哦 !!! 本篇文章帮你逐个击破以下几个问题: 01 靠谱的简历投递方式有哪些? 02 接到对方的电话面试通知,你在忙该怎么办? 03 面试时,一开始你不知道说些什么,该怎么办? 04 手忙脚乱…

金九银十,从简历投递到offer审批,入职腾讯我只用了七天

9月底投岗腾讯后台开发&#xff0c;历经3面技术HR面offer审批&#xff0c;我却只花了7天时间就上岸成功了... 文末分享一些我的经验之谈&#xff0c;敬请期待... 9-22 投递简历 9-24 一面&#xff08;大概1h50min&#xff09; osi七层网络模型&#xff0c;五层网络模型&#…

我是如何 2 个月拿到 4 份 Offer 并收入翻倍的?

作者 | minus 责编 | 伍杏玲 本文经授权转载自石杉的架构笔记 先做个自我介绍&#xff0c;楼主坐标帝都&#xff0c;5年经验&#xff0c;跳槽之前在一家传统小公司&#xff0c;年薪21万。 这次面试前前后后大概两个月的时间&#xff0c;面试了大概6家公司&#xff0c;命中4…

offer(第二版)2021-06-02

还差差14个题完结 面试题1&#xff1a;赋值运算符函数 面试题2&#xff1a;实现Singleton模式 面试题3&#xff1a;数组中重复的数字 面试题4&#xff1a;二维数组中的查找 面试题5&#xff1a;替换空格 面试题6&#xff1a;从尾到头打印链表 面试题7&#xff1a;重建二…

一文带你玩转offer-01

文章目录 1.RabbitMq是如何实现消息路由的1.1 工作流程1.2 路由策略Direct ExchangeTopic ExchangeFanout Exchange 2.谈谈你对时间轮的理解2.1 什么是时间轮2.2 时间轮的工作原理2.3 时间轮优缺点分析 3.什么是幂等&#xff1f;如何解决幂等性问题3.1 什么是幂等3.2 如何解决幂…

和HR谈了5min包裹,刚拿到的offer又被撤回了...

最近&#xff0c;在网上看到很多人都分享了自己谈薪失败&#xff0c;导致offer被revoke的情况。 撤回就算了&#xff0c;更惨的是&#xff0c;还有可能会被该公司列入黑名单。 Offer被revoke很常见&#xff0c;不过在求一个面试机会都难的今年&#xff0c;到手的offer被撤就显得…

您有一份OFFER请查收!

我们总以为生活欠我们一个“满意” 其实我们欠生活一次“尝试” 爱可生正在招人 快来投简历尝试下吧&#xff01;&#x1f914; 如果你 想看到 金融银行体系对数据高可用性要求达99.9999%&#xff0c; 严格要求数据一致性的场景下 数据库如何选型、如何运维&#xff1f;…

记一次腾讯社招前端面试(已拿到offer入职)

作者&#xff1a;小冷^_^ 链接&#xff1a;https://juejin.im/post/5dde65496fb9a07161483fc9 笔者信息 我某211非计算机相关专业2018届本科生&#xff0c;在校期间实习有半年多的小公司Java开发实习经历&#xff0c;毕业之后投递360&#xff0c;入职了360企业安全成为专门的前…

刚收到了Facebook的Offer,我是这样为面试做准备的?

点击上方“程序员大咖”&#xff0c;选择“置顶公众号” 关键时刻&#xff0c;第一时间送达&#xff01; 我刚刚在硅谷的科技公司完成了7次现场面试&#xff0c;我收到了来自Facebook的软件工程师的职位Offer。下面分享一下我是怎么为面试做准备的&#xff0c;以及我在这个过程…

自学测试半年,我终于收到了腾讯的offer,收到消息的那一刻我哭出了声...

我是一名毕业于普通一本的化学专业学生&#xff0c;毕业的两年时间里&#xff0c;我一直奔波在化工厂里。每天工作三班倒&#xff0c;下了班就是一包烟一瓶酒&#xff0c;生活过得非常堕落。 原本想着虽然每天很累&#xff0c;但是至少稳定。然而没有想到的是&#xff0c;化工…

ChatGPT如何帮助DevOps提升效率

DevOps 是一种方法论&#xff0c;旨在提高软件开发和 IT 运营团队的协作和效率。DevOps 涉及各种任务和流程的自动化&#xff0c;例如规划、编码、测试、部署、监控和故障排除。然而&#xff0c;其中一些任务和流程仍然有大量任务需要人工手动处理&#xff0c;而这会减慢软件产…