实践指南:EdgeOne与HAI的梦幻联动
在当今快速发展的数字时代,安全和速度已成为网络服务的基石。EdgeOne,作为腾讯云提供的边缘安全加速平台,以其全球部署的节点和强大的安全防护功能,为用户提供了稳定而高效的网络体验。而HAI(HyperApplicationInventor),腾讯云推出的高性能应用服务,通过其易用的图形化界面和丰富的模型库,使得AI应用开发变得触手可及。本文将探讨EdgeOne与HAI的结合如何为用户提供一个既安全又高效的AI应用开发环境。
EdgeOne:全球加速与安全防护
- DDoS防护:EdgeOne使用Anycast架构在全球建立超过25个清洗中心,能快速检测并清除网络、传输和应用层的DDoS攻击。
- WEB攻击防护:EdgeOne拥有广泛的攻击特征库,覆盖主要的安全威胁,能阻止各类Web攻击并防御0day漏洞,通过AI提高检测准确性,减少误报。
- 智能CC识别:EdgeOne利用多年经验,通过分析网络流量和多种参数,自动识别并定位攻击源,有效对抗CC攻击。
- BOT防护:EdgeOne通过协议、IP和会话特征识别BOT,结合数据分析建立模型,防止恶意爬虫攻击,减少对正常爬虫的误伤。
- 攻击溯源:EdgeOne可以捕获并分析异常事件,提取攻击信息,提供监控页面展示攻击详情,帮助用户调整防护策略。
- 全天候监测:腾讯安全团队24/7实时监控,主动发现并应对威胁,快速响应安全事件。
不多说了,剩下的内容都已经在官方文档中有详细描述。就我们个人而言,EdgeOne具有以下主要优点,并且我也附上了需要的关键文档地址:
- 干净流量计费模式:对于安全防护功能拦截的请求不进行计费。这种计费模式的优势在于,用户无需担心因网络攻击而产生的额外费用,可以更加专注于业务的发展和优化。
- 免费证书:简化HTTPS部署,官方文档:https://cloud.tencent.com/document/product/1552/90437
- 个人版套餐升级:CC防护与自定义规则设置,官方文档:https://cloud.tencent.com/document/product/1552/93128
- 无域名接入:快速启用四层代理服务,这个得需要企业认证,个人慎选。官方文档:https://cloud.tencent.com/document/product/1552/96051
- 自助诊断:快速定位问题,通过输入诊断链接,用户可以快速获得诊断报告和解决指引,从而提高问题解决的效率。官方文档:https://cloud.tencent.com/document/product/1552/81229
- 折扣活动:年度最低价,性价比之选,官方文档:https://cloud.tencent.com/document/product/1552/96920
- 无域名接入功能,快速接入 EdgeOne 启用四层代理服务。https://cloud.tencent.com/document/product/1552/96051
HAI:AI应用的快速开发
HAI提供了可视化交互界面,支持JupyterLab、WebUI等多种算力连接方式,使得用户即使没有深厚的编程背景也能轻松开发AI应用。这种“有手就能开发”的设计理念,极大地降低了AI技术的应用门槛。支持学术加速,通过线路自动择优,能够大幅提升主流学术资源平台的访问、下载速度。同时,HAI预装了StableDiffusion、ChatGLM等热门模型,用户可以在数分钟内构建自己的大语言模型、AI作画等应用环境。
这个话题不需要详细讨论了,我已经整理了开发中需要了解的主要优点和相关文档,以便大家能够快速入手开发:
- 快速部署:创建高性能应用服务实例,选择合适的地域、算力方案,并设置实例名称和硬盘空间。官方文档:https://cloud.tencent.com/document/product/1721/101036
- 生成API文档:在已部署的Stable Diffusion应用基础上,通过JupyterLab部署API服务。官方文档:https://cloud.tencent.com/document/product/1721/102198
- 模型下载地址:https://civitai.com/
- 导入外部模型:在腾讯云高性能应用服务HAI上,可以通过三种方式导入外部模型,但是为了花钱少一点,我推荐你选择COS存储。官方文档:https://cloud.tencent.com/document/product/1721/102523#1bb64c7b-0bc8-4a2a-86f0-ad0e71d8f059
联动开发
现在让我们来探讨一下为何可以采用联动开发的方式。我们的目标是以最为经济实惠的价格部署我们的AI绘画应用。
- HAI高性能服务器是按照小时收费的,所以我们很多情况下会选择关机,但是一旦重启服务器,外网IP就会变动,导致你的访问路径也就随之变换。但是这一步可以在EdgeOne中使用边缘函数解决。
- EdgeOne本身就已经对我们的服务器做了相应的安全防护。
- HAI高性能服务器,他是一个Ubuntu20.04环境的虚拟机,也就是说,我们已经有了一个服务器,只不过这个服务器被包装成了绘画AI应用,所以不要浪费掉。用起来
我们接下来看下我们会用到哪些技术:HTML、Javascript、CSS、Nginx、Python、边缘函数中的各个API、Linux基本命令。
准备环境
HAI高性能服务器
关于创建服务器的步骤,我就不再进行演示了,请直接查看官方教程,相关地址也已经提供。我们将重点演示以下内容:下载/上传模型、通过WEB UI演示AI绘画功能、下载并配置Nginx以监听80端口、启动API接口服务。
下载/上传模型
这一步我当时使用过如何官方默认的JupyterLab页面上传,速度是真的很可观~我直接放弃了。选择了COS对象存储。我们先去下载好看的模型。这里以https://civitai.com/ 为例。
模型下载到本地之后,去创建COS对象存储服务。
如何创建这么简单的教程,我就不演示了,我们直接看上传和下载。这里创建存储桶的时候,所属地域一定要和你HAI绘画服务器在一起。否则会产生很多额外的花销。谨记~
进入存储桶之后,直接点击页面的上传文件即可,请选择刚才下载的模型文件。上传的过程中不要动浏览器,一旦刷新和关闭浏览器就会前功尽弃。
稍等片刻,然后点击模型文件的详情,进入基本信息页面。在这里,请确保将权限设置为公有读取,否则HAI服务器将无法下载到模型文件。然后,复制临时链接。
我们进入已经创建好的HAI服务器。
进入终端,使用一下几个命令,下载模型文件到模型文件夹。
cd stable-diffusion-webui/models/Stable-diffusion
wget 临时链接粘贴到此处
等待下载完毕。
WEB UI演示AI绘画
让我们前往WEB UI页面,尝试一下看看是否成功安装了。
在WEB UI页面上,选择您自己的模型文件,并使用一段神奇的提示词。当然,提示词越好,生成的结果也会越好。如果有任何不清楚的地方,您可以参考您下载的模型附带的教程。这样基本上就没有问题了。接下来,让我们再来看看如何让HAI提供站点服务。
Nginx站点配置
依然是同样的步骤,在JupyterLab中的终端中直接使用以下命令操作:
- 下载Nginx:使用命令
apt install nginx
进行安装。 - 启动Nginx:使用命令
service nginx start
启动服务。
当您直接使用IP地址在浏览器中访问后,如果显示以下界面,那就表示安装成功了。
接下来,我们继续修改Nginx的配置文件:
使用以下命令编辑配置文件:
vim /etc/nginx/sites-available/default
然后,在文件中添加以下配置:
# 配置/images路径的访问规则
location /images/ {add_header 'Access-Control-Allow-Origin' "$http_origin";add_header 'Access-Control-Expose-Headers' 'strict-origin-when-cross-origin';alias /root/stable-diffusion-webui/outputs/star/images/; # 你的静态页面expires 1d;}
location /sdapi/ {# Add CORS headersadd_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;proxy_pass http://127.0.0.1:7862/sdapi/;if ($request_method = "OPTIONS"){return 200;}}
这里配置了/images路径的访问规则以及API服务的代理。为什么要配置代理呢?这显然是因为绘画的API服务不支持跨域访问,所以我们添加了一个反向代理。由于我们的请求是POST非简单请求,因此浏览器还会发送一个OPTIONS的预检请求。我也做了相应的处理。以免跨域报错。
修改完成后,使用命令 service nginx reload
来重新加载Nginx的配置。您可以看到我们配置的/images路径对应的文件。这个路径您可以随心配置,只要确保其中包含您自己的图片即可。您可以选择自己维护这些图片,也可以通过程序生成。为了演示,我只简单复制了几张我使用AI绘画出来的图片。
让我们通过Nginx来访问一下图片,以确保可以正常访问。
在浏览器中输入以下地址进行访问:http://你的IP/images/1.png
接下来,我们继续调试API服务。请启动HAI绘画应用的API服务,使用以下命令:
python launch.py --nowebui --xformers --opt-split-attention --listen --port 7862
然后,在浏览器中输入IP地址和端口号,后面加上/docs路径即可正常访问路径了。
让我们通过工具来测试一下,看看能否通过Nginx正常访问接口。你可以随意选择一个接口路径进行测试。我选择了一个简单的无请求参数的GET请求作为示例。通常情况下,这个请求会带有端口号。
使用调试工具来调用一下Nginx配置的路径,确保一切正常。
如果您还不确定的话,可以通过查看默认的Nginx访问路径来确认。您可以使用以下命令来实时查看日志:
tail -f /var/log/nginx/access.log
这样您就可以确定API是否能够被正确命中。
启动API接口服务
为了解决Nginx每次关机后无法正常启动的难题,我们采取了一项巧妙的解决方案:将启动命令直接写入API启动服务接口中,从而确保服务能够在每次启动时正确配置Nginx。具体操作如下:首先,我们需要找到项目中的launch.py文件。一旦找到了该文件,我们只需在其中添加几行命令即可。这些命令将确保Nginx在服务器启动时得到正确的配置,并能够顺利启动。这种方法简单而高效,能够有效解决Nginx启动问题,保证服务的稳定性和可靠性。
代码如下:
import subprocess# 此处省略很多代码~~
def main():# 使用subprocess.run()执行命令result = subprocess.run(['service', 'nginx', 'start'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)# 检查命令是否执行成功if result.returncode == 0:print("Nginx 已成功启动")else:print("启动 Nginx 时出错")print("错误信息:", result.stderr)# 此处省略很多代码~~
为了验证我们的解决方案的有效性,让我们再次重新启动API服务,观察是否能够成功启动Nginx。
通过以上步骤,我们的HAI高性能服务器已经完成了基本配置。无论进行多少次关机重启,我们的Nginx都会随着API接口一起启动,确保了系统的稳定性和可靠性。现在,让我们继续深入探讨EdgeOne的配置过程。
EdgeOne边缘函数
在配置EdgeOne时,首先需要确保完成无域名站点的配置,你可以直接参考官方文档进行操作。接着,我们需要创建边缘函数来实现相应的缓存处理。考虑到你没有企业版权限,因此无法使用四层加速,但可以通过边缘函数来达到类似的效果。关于边缘函数中代码的具体使用问题,我建议你仔细阅读官方文档,其中包含了详细的操作指南和示例代码,可以帮助你快速上手。你可以点击以下链接查看官方文档:EdgeOne 官方文档
在配置边缘函数时,你可以选择Hello World模板作为起点,然后依次点击下一步进行配置。虽然选择了Hello World模板,但它只是一个起点,我们将在此基础上进行深入的定制,以实现我们所需要的功能。
完成所有配置后,系统会为你生成一个默认的域名。接下来,我们需要编写代码来实现功能。通常情况下,我会额外编写一个test函数,专门用于测试。当然,如果你觉得不需要,也可以忽略。在这次配置中,我们创建了两个边缘函数。这些函数已经经过我封装,通过最小的变动来应对HAI服务器外网IP的变化,确保了系统的稳定性和可靠性。
查询图片处理
一个绘画应用的关键之一在于能够提供优质的图片展示功能。毕竟,画作的视觉效果是吸引用户的关键之一。缺少了图片展示功能,这个应用就好比是一本没有插图的画册,缺乏吸引力,难以引起用户的兴趣。
async function fetchJquery(event, request) {const cache = caches.default;// 缓存没有命中,回源并缓存let response = await fetch(request);// 在响应头添加 Cahe-Control,设置缓存时长 10sresponse.headers.append('Cache-Control', 's-maxage=600');event.waitUntil(cache.put(request, response.clone()));// 未命中缓存,设置响应头标识response.headers.append('x-edgefunctions-cache', 'miss');return response;
}async function handleEvent(event) {const urlInfo = new URL(event.request.url);var url = new URL(event.request.url);var ip = url.searchParams.get('ip');// 请求非图片资源if (!/\.(jpe?g|png)$/.test(urlInfo.pathname)) {return event.respondWith(new Response('Error thrown 没命中图片URL' + urlInfo.pathname));}// 资源地址,也作为缓存键const request = new Request(ip + urlInfo.pathname);// 缓存默认实例const cache = caches.default;try {// 获取关联的缓存内容,缓存过,接口底层不主动回源,抛出 504 错误let response = await cache.match(request);// 缓存不存在,重新获取远程资源if (!response) {return fetchJquery(event, request);}// 命中缓存,设置响应头标识response.headers.append('x-edgefunctions-cache', 'hit');return response;} catch (e) {await cache.delete(request);// 缓存过期或其他异常,重新获取远程资源return fetchJquery(event, request);}
}addEventListener('fetch', (event) => {event.respondWith(handleEvent(event));
});
这段代码的主要功能是用于处理网络请求并管理资源的缓存策略,确保快速响应用户请求的同时,减少不必要的网络流量。
fetchJquery
函数:- 该函数用于处理当资源未被缓存或缓存过期时的情况。
- 使用
fetch
函数发起网络请求,获取资源的最新响应。 - 在响应头中添加
Cache-Control
,设置资源在服务端缓存中的最长有效时间为600秒。 - 使用
cache.put
方法将获取的响应克隆一份并存入缓存中,以便后续请求可以直接从缓存中获取。 - 设置响应头
x-edgefunctions-cache
为miss
,表示这是一个未命中缓存的请求。 - 返回原始响应给请求者。
handleEvent
函数:- 该函数用于检查请求的URL是否指向一个图片资源(通过文件扩展名判断)。
- 如果请求的不是图片资源,将返回一个错误响应。
- 如果是图片资源,尝试从缓存中获取请求的资源。
- 如果缓存中存在资源,则设置响应头
x-edgefunctions-cache
为hit
,表示这是一个命中缓存的请求,并返回缓存中的资源。 - 如果缓存中不存在资源或发生异常(如缓存过期),则删除缓存并重新调用
fetchJquery
函数获取资源。
在访问图片资源时,需要特别注意的是,我采用了路径后面的 IP 参数进行访问。这是因为 HAI 每次重启后外网 IP 都会发生变化,如果每次都要修改每个边缘函数的话,会相当繁琐。为了避免这种情况,我选择通过参数传递的方式来获取图片资源。这样一来,获取图片资源的边缘函数就不需要再进行任何修改了。另外,你还需要对匹配触发规则进行配置,比如我设置的规则是包含 “/images” 的路径才会触发相应的操作。
在浏览器中输入默认域名,并随意添加 “/images/*.png” 即可访问相应图片,前提是该图片存储于我们的服务器上。现在让我们来观察一下效果。值得注意的是,这种方式的命中率并不是很高,所以在刚部署完边缘函数后,需要多刷新几次才能看到效果。
静态网页
这个边缘函数专门用于处理用户交互。
const html = `
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI绘图</title><style>body {font-family: Arial, sans-serif;}.container {display: flex;justify-content: center;}.box {margin: 20px;border: none; /* 移除框的边框 */padding: 10px;background-color: #f5f5f5; /* 设置框的背景颜色 */border-radius: 10px; /* 添加圆角 */display: flex; /* 使用flex布局 */flex-direction: column; /* 垂直布局 */align-items: center; /* 居中对齐 */text-align: center; /* 文字居中对齐 */}.box:nth-child(2) {align-self: start; /* 右边的box顶部对齐 */}.box-title {margin-bottom: 10px;margin-right: 500px;border-bottom: 1px solid grey; /* 添加标题底部的分隔线 */padding-bottom: 5px; /* 添加一些底部间距以增强视觉效果 */}#image-container {width: 512px;height: 512px;background-color: #eee;margin: auto; /* 在父元素中水平居中 */}#text-description {width: 300px;height: 100px;margin-bottom: 10px;border: 1px solid grey; /* 添加外边框 */padding: 5px;resize: none; /* 禁止调整大小 */font-size: 14px;outline: none; /* 移除输入框默认的外边框 */border-radius: 0; /* 移除圆角 */}#text-description2 {width: 300px;height: 100px;margin-bottom: 10px;border: 1px solid grey; /* 添加外边框 */padding: 5px;resize: none; /* 禁止调整大小 */font-size: 14px;outline: none; /* 移除输入框默认的外边框 */border-radius: 0; /* 移除圆角 */}#dropdown {padding: 10px 20px; /* 增大按钮的内边距 */cursor: pointer;margin-bottom: 10px;border: 1px solid grey; /* 添加外边框 */width: 100%; /* 将宽度设置为100%以与容器对齐 */align-self: flex-start; /* 按钮左对齐 */}#dropdown2 {padding: 10px 20px; /* 增大按钮的内边距 */cursor: pointer;margin-bottom: 10px;border: 1px solid grey; /* 添加外边框 */width: 100%; /* 将宽度设置为100%以与容器对齐 */align-self: flex-start; /* 按钮左对齐 */}#acckey {padding: 10px 20px; /* 增大按钮的内边距 */cursor: pointer;margin-bottom: 10px;border: 1px solid grey; /* 添加外边框 */width: 100%; /* 将宽度设置为100%以与容器对齐 */align-self: stretch; /* 按钮左对齐 */}#input-container {flex-grow: 1;display: flex;flex-direction: column; /* 垂直布局 */align-items: center; /* 居中对齐 */}#text-input {width: 300px;height: 30px;margin-bottom: 10px;}#generate-button {padding: 10px 20px; /* 增大按钮的内边距 */background-color: #4caf50;color: white;border: none;cursor: pointer;width: 100%; /* 将宽度设置为100%以与容器对齐 */align-self: flex-start; /* 按钮左对齐 */}@media (max-width: 600px) {.container {flex-wrap: wrap; /* 在屏幕宽度不足时换行显示 */}.box {width: 100%; /* 让框占满一行 */margin-bottom: 20px; /* 添加底边距 */}}.image-list {display: flex; /* 使用flex布局 */flex-wrap: wrap; /* 允许列表换行 */justify-content: space-around; /* 间隔均匀分布 */align-items: center; /* 垂直居中对齐 */}.image-list img {max-width: 18%; /* 图片最大宽度占比,根据需要调整 */margin: 5px; /* 图片之间的间隔 */object-fit: contain; /* 确保图片等比例缩放 */}</style>
</head>
<body><div class="container"><div class="box"><h2 class="box-title">绘图结果</h2><div id="image-container"></div></div><div class="box"><h2 class="box-title">文本描述</h2><div id="input-container"><textarea id="text-description" title="文本描述" placeholder="文本描述。
算法将根据输入的文本智能生成与之相关的图像。建议详细描述画面主体、细节、场景等,文本描述越丰富,生成效果越精美。
不能为空,推荐使用中文。最多传512个字符。"></textarea><textarea id="text-description2" title="反向文本描述" placeholder="反向文本描述。
用于一定程度上从反面引导模型生成的走向,减少生成结果中出现描述内容的可能,但不能完全杜绝。
推荐使用中文。最多传512个字符。"></textarea><select id="dropdown" title="分辨率"><option value="768:1024">分辨率(默认768:1024)</option><option value="768:768">768:768</option><option value="1024:768">1024:768</option></select><select id="dropdown2" title="绘画风格"><option value="201">绘画风格(默认日系动漫风格)</option></select><div style="display: flex; justify-content: flex-start; width: 100%;"><input id="acckey" type="password" placeholder="访问密钥" style="width: 100%;"></div><button id="generate-button">生成</button></div></div></div><!-- 图片列表容器 --><div class="image-list" id="image-list"><!-- 图片将被动态插入到这里 --></div><script>// 页面加载完成后执行的函数window.onload = function() {// 假设您已经有了一个函数来发起请求和处理响应// 这里我们直接调用这个函数createImageList();};var ip = "http://101.43.51.133";document.getElementById("generate-button").addEventListener("click", function() {var Ai_Image_Prompt = document.getElementById("text-description").value;var Ai_Image_NegativePrompt = document.getElementById("text-description2").value;var Ai_Image_Size = document.getElementById("dropdown").value;var Ai_Image_Styles = document.getElementById("dropdown2").value;var Ai_Image_AccKey = document.getElementById("acckey").value;var data = {"denoising_strength": 0,"override_settings": {"sd_model_checkpoint" :"animagineXLV31_v30.safetensors [1449e5b0b9]"}, "prompt": Ai_Image_Prompt,"negative_prompt": Ai_Image_NegativePrompt,"seed": 0,"batch_size": 1,"n_iter": 1,"num_inference_steps": 28,"guidance_scale": 7,"sdxl_style": "(None)","quality_tags": "(None)","width": 512,"height": 512,"sampler": "Euler a"};var xhr = new XMLHttpRequest();xhr.open("POST", ip + "/sdapi/v1/txt2img", true);xhr.setRequestHeader("Content-Type", "application/json");xhr.onreadystatechange = function() {if(xhr.readyState === 4){if (xhr.status === 200) {var response = JSON.parse(xhr.responseText);var imageContainer = document.getElementById("image-container"); // 创建一个新的img元素var imgElement = document.createElement("img");imageContainer.style.backgroundSize = "contain";// 设置img元素的src属性为base64编码的图片数据imgElement.src = 'data:image/png;base64,'+response.images[0];// 设置img元素的alt属性imgElement.alt = "动态生成的图片";// 将img元素添加到imageContainer中imageContainer.appendChild(imgElement);// 由于img元素是异步加载的,我们需要等待图片加载完成后再进行操作}else{alert("请求错误:" + xhr.status);}}};xhr.onerror = function() {// 处理网络错误alert("网络错误");};xhr.send(JSON.stringify(data));});// 处理图片列表的函数function createImageList() {var imageList = document.getElementById("image-list");imageList.innerHTML = ""; // 清空当前列表// 使用for循环生成图片元素for (var i = 1; i <= 5; i++) {// 创建新的img元素var img = document.createElement("img");// 设置图片的src属性为对应的图片文件路径// 假设所有图片都存放在同一个目录下img.src = "http://ai-zone-2vjn2f1z4giq-1302107156.eo-edgefunctions.com/images/" + i + ".png?ip="+ip;img.alt = "Image " + i; // 设置alt属性img.style.width = '100%'; // 设置图片宽度为100%// 将img元素添加到图片列表容器中imageList.appendChild(img);}}
</script></body>
</html>`;
async function handleRequest(request) {
return new Response(html, {
headers: {
'content-type': 'text/html; charset=UTF-8',
'x-edgefunctions-test': 'Welcome to use Edge Functions.',
},
});
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
这段代码定义了一个HTML页面,用于展示一个AI绘图应用的用户界面,并包含了与之交互的JavaScript代码。主要功能和组成部分如下:
- HTML结构:
- 页面包含一个容器
container
,用于布局两个主要部分:绘图结果展示和文本描述输入。 - 绘图结果部分包含一个标题和一个图像容器
image-container
,用于展示AI生成的图像。 - 文本描述部分包含两个文本区域
text-description
和text-description2
,供用户输入正向描述和反向描述,用于指导AI绘图。 - 一个按钮
generate-button
,用于触发AI绘图过程。
- 页面包含一个容器
- JavaScript逻辑:
- 页面加载完成后,调用
createImageList
函数,动态生成一个图片列表并展示在页面上。 - 监听
generate-button
按钮的点击事件,收集用户输入的描述和选择的参数,构造一个AI绘图请求,并发送到服务器。 - 使用
XMLHttpRequest
对象发送POST请求到指定的服务器地址,处理响应并动态更新页面上的图像容器以展示生成的图像。
- 页面加载完成后,调用
我们看一下最终效果:
我已经将 IP 地址单独抽离出来,以确保最小化变动量。如果需要重启,只需更新 IP 地址,然后重新部署即可重新访问。
让我们再次观察一下生成图片的效果。点击生成时,后台接口的响应也都是正常的。
质量确实还有提升空间,我仔细检查了一下,发现问题可能出在模型的限制上。例如,对于宽高比不能是正方形的图像,可以稍微宽一点或高一点。这样生成的图像会更具观赏性。但这些问题都是可以通过调试解决的。总的来说,我们的EdgeOne和HAI的梦幻联动已经取得了阶段性的成果,算是告一段落了。
总结
本篇文章源于他人创意的启发与深入思考,我投入了大量时间与精力,致力于EdgeOne与HAI之间的协同调试,克服了众多技术奇葩问题。通过不懈的努力,成功地将这两个强大的平台整合在一起,打造出一个还不错的参考案例。这次探索也是我个人首次涉足边缘函数式产品的实践之旅。我希望通过分享这次的经历和成果,能够激发更多人对这些前沿技术的兴趣和探索。如果你对我的项目感兴趣,或者从中获得了灵感与帮助,不妨点赞支持,也欢迎关注我,一起交流学习,共同进步。
相关文章:
实践指南:EdgeOne与HAI的梦幻联动
在当今快速发展的数字时代,安全和速度已成为网络服务的基石。EdgeOne,作为腾讯云提供的边缘安全加速平台,以其全球部署的节点和强大的安全防护功能,为用户提供了稳定而高效的网络体验。而HAI(HyperApplicationInventor…...
OmniDiskSweeper :一款专为 macOS 设计的磁盘使用分析工具
OmniDiskSweeper 是一款专为 macOS 设计的磁盘使用分析工具,由 The Omni Group 开发。它的主要目的是帮助用户可视化磁盘上的文件和文件夹,并找出占用大量空间的文件,从而帮助用户释放磁盘空间。 OmniDiskSweeper 的特点包括: 简…...
【Git】:Git基本操作
目录 创建、配置本地仓库 创建本地仓库 配置本地仓库 认识工作区、暂存区、版本库 修改文件 版本回退 撤销修改 删除文件 创建、配置本地仓库 创建本地仓库 我们通常可以通过以下两种方式之一获取 Git 存储库: 自己在本地目录创建一个本地仓库 从其它服务…...
C++设计模式:建造者模式(Builder) 房屋建造案例
什么是建造者模式? 建造者模式是一种创建型设计模式,它用于一步步地构建一个复杂对象,同时将对象的构建过程与它的表示分离开。简单来说: 它将复杂对象的“建造步骤”分成多部分,让我们可以灵活地控制这些步骤。通过…...
由于centos停更,yum、docker等不支持,采用阿里云仓库搭建K8S
一:准备 服务器信息主机名IP地址Centos7.9node1-master192.168.35.130Centos7.9node2192.168.35.131 # 查看系统版本 cat /etc/centos-release # 查看内核版本 uname -sr二:服务器前置操作 每个节点都需要操作 #使用 hostnamectl set-hostname设置主机…...
cocos creator 3.8 一些简单的操作技巧,材质的创建 1
这是一个飞机的3D模型与贴图 导入到cocos中,法线模型文件中已经包含了mesh、material、prefab,也就是模型、材质与预制。界面上创建一个空节点Plane,将模型直接拖入到Plane下。新建材质如图下 Effect属性选择builtin-unlit,不需…...
下载安装Android Studio
(一)Android Studio下载地址 https://developer.android.google.cn/studio 滑动到 点击下载文档 打开新网页 切换到english 
随着人口老龄化进程的加速,摔倒事故逐渐成为威胁老年人健康和安全的主要问题之一。研究表明,摔倒不仅可能导致老年人骨折、头部受伤等严重的身体损伤,还可能引发心理恐惧和行动能力下降,从而降低其生活质量和独立性。如何快速、准…...
C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的类、不能被继承的类、单例模式)
C特殊类设计 在实际应用中,可能需要设计一些特殊的类对象,如不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类、只能创建一个对象的类(单例模式)。 1. 不能被拷贝的类 拷贝只会发生在两个场景…...
Javaweb前端HTML css 整体布局
最后一个是线条颜色 盒子,整体还是300,400...
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 贵在坚持! 数据样例项目地址: * 相关项目 1)数据集…...
【从零开始的LeetCode-算法】3297. 统计重新排列后包含另一个字符串的子字符串数目 I
给你两个字符串 word1 和 word2 。 如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀,那么我们称字符串 x 是 合法的 。 请你返回 word1 中 合法 子字符串的数目。 示例 1: 输入:word1 "bcca", word2 "…...
【Redis_Day5】String类型
【Redis_Day5】String类型 String操作String的命令set和get:设置、获取键值对mset和mget:批量设置、获取键值对setnx/setex/psetexincr和incrby:对字符串进行加操作decr/decrby:对字符串进行减操作incrbyfloat:浮点数加…...
【CVE-2024-48694】OfficeWeb365 SaveDraw
漏洞描述 OfficeWeb365 v.8.6.1.0和v7.18.23.0中的文件上传漏洞允许远程攻击者通过pw/savedraw组件执行任意代码。 影响版本: V8.6.1.0; V7.18.23.0 网络测绘 “OfficeWeb365” 漏洞信息 POST /PW/SaveDraw?path../../Content/img&idx6.ashx H…...
leecode134.加油站
一开始想的是总体上加油量超过耗油量那么就一定能找到一个起始点可以跑一圈,这个起始点选择补充油量与耗油量差值最大的那gas个点,但是我没仔细审题,这个起始点是索引逐次1绕一圈而不是随便选择,gas[5,8,2,8],cost[6,5…...
分层架构 IM 系统之 Entry 部署模式
在前面的一篇技术短文(分层架构 IM 系统之架构解读)中,对【分层架构】进行了详细分析;今天我们聊一下【入口层】Entry 的部署模式。 Entry 作为 IM 系统整个后端集群的入口,直接与客户端建立 TCP 长连接,E…...
【Java从入门到放弃 之 多线程 四】
多线程 四 多线程 四读写锁的使用代码演示 乐观锁的使用代码演示 信号量代码演示 倒计时门禁代码演示 循环栅栏Condition详解代码案例 多线程 四 读写锁的使用 上一篇我们介绍到了可重入锁,现在我们来介绍读写锁。实际上,使用可重入锁的时候我们就可以…...
OpenHarmony-3.驱动HDF
OpenHarmony HDF 框架 1.OpenHarmony HDF 框架概述 OpenHarmony驱动子系统采用C面向对象编程模型构建,通过平台解耦、内核解耦,兼容不同内核,提供了归一化的驱动平台底座,旨在为开发者提供更精准、更高效的开发环境,力…...
udp_socket
文章目录 UDP服务器封装系统调用socketbind系统调用bzero结构体清0sin_family端口号ip地址inet_addrrecvfromsendto 新指令 netstat -naup (-nlup)包装器 的两种类型重命名方式包装器使用统一可调用类型 关键字 typedef 类型重命名系统调用popen关于inet_ntoa UDP服务器封装 系…...
Java NIO 核心知识总结
在学习 NIO 之前,需要先了解一下计算机 I/O 模型的基础理论知识。还不了解的话,可以参考我写的这篇文章:Java IO 模型详解。 一、NIO 简介 在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。…...
音频信号采集前端电路分析
音频信号采集前端电路 一、实验要求 要求设计一个声音采集系统 信号幅度:0.1mVpp到1Vpp 信号频率:100Hz到16KHz 搭建一个带通滤波器,滤除高频和低频部分 ADC采用套件中的AD7920,转换率设定为96Ksps ;96*161536 …...
PyTorch基础学习03_数学运算自动微分
目录 一、数学运算 1、基本操作 2、三角函数 3、统计学函数 二、保存和加载 三、并行化 四、自动微分 1、相关概念 2、计算梯度 1.标量梯度计算 2.向量梯度计算 3.多标量梯度计算 4.多向量梯度计算 5.矩阵梯度计算 3、梯度上下文控制 1、梯度控制 2、梯度更新…...
HarmonyOS4+NEXT星河版入门与项目实战(16)------ 状态管理 @State(页面数据刷新与渲染)
文章目录 1、@State装饰器2、视图渲染演示1、无嵌套的对象属性值变化时可以触发页面渲染2、嵌套对象的嵌套属性值变化时不能够触发页面刷新渲染3、数组中对象的属性值变化时不能触发页面刷新渲染3、总结1、@State装饰器 2、视图渲染演示 常规的 string、number 这里就不演示了…...
K8s 一键部署 MongoDB 的 Replica-Set 和 MongoDB-Express
什么是 MongoDB 副本集? MongoDB 副本集(Replica-Set)是一个分布式数据库系统,它包含一个主节点和多个从节点。主节点负责处理所有写操作,从节点用于读取数据。当主节点发生故障时,从节点可以自动选举一个…...
React Native的界面与交互
React Native (RN) 是一个由 Facebook 开发的开源框架,用于构建跨平台的移动应用程序。它允许开发者使用 JavaScript 和 React 来创建原生 iOS 和 Android 应用。RN 的出现极大地简化了移动应用的开发过程,使得开发者可以更快速、更高效地构建高质量的应…...
【探寻密码的奥秘】-001:解开密码的神秘面纱
目录 1、密码学概述1.1、概念1.2、目的1.3、应用场景 2、密码学的历史2.1、第一时期:古代密码时代2.2、第二时期:机械密码时代2.3、第三时期:信息密码时代2.4、第四时期:现代密码时代 3、密码学的基本概念3.1、一般通信系统3.2、保…...
C++实现Raft算法
概念部分 Raft 算法是一种用于实现分布式系统中的一致性的算法。它是为了容易理解而设计的,其目标是实现和 Paxos 算法相同的功能,但更加容易理解和实现。Raft 算法在分布式系统中尤其关键,因为它帮助系统中的多个节点就其数据的准确状态达成…...
FastApi教程
FastAPI框架 fastapi,一个用于构建 API 的现代、快速(高性能)的web框架。 fastapi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/…...
HTB:WifineticTwo[WriteUP]
目录 连接至HTB服务器并启动靶机 信息搜集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用curl访问靶机8080端口 使用浏览器直接访问/login路径 漏洞利用 使用searchsploit搜索该WebAPP漏洞 Payload USER_FLAG:bb…...
ubuntu16.04在ros使用USB摄像头-解决could not open /dev/video0问题
首先检查摄像头 lsusb 安装 uvc camera 功能包 sudo apt-get install ros-indigo-uvc-camera 安装 image 相关功能包 sudo apt-get install ros-kinetic-image-* sudo apt-get install ros-kinetic-rqt-image-view运行 uvc_camera 节点 首先输入roscore 然后另外开一个终端输入…...
大模型专栏--什么是大模型
什么是大模型 来自 chatGPT 的回答: “大模型”通常指的是在机器学习和深度学习领域,尤其是自然语言处理(NLP)和计算机视觉(CV)中,具有大量参数和复杂结构的模型。这些模型通常需要大量的数据和…...
LLaMA-Mesh: Unifying 3D Mesh Generation with Language Models 论文解读
目录 一、概述 二、相关工作 1、LLMs到多模态 2、3D对象生成 3、自回归的Mesh生成 三、LLaMA-Mesh 1、3D表示 2、预训练模型 3、有监督的微调数据集 4、数据集演示 四、实验 1、生成的多样性 2、不同模型text-to-Mesh的比较 3、通用语境的评估 一、概述 该论文首…...
golang实现TCP服务器与客户端的断线自动重连功能
1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功...
项目实战:基于深度学习的人脸表情识别系统设计与实现
大家好,人脸表情识别是计算机视觉领域中的一个重要研究方向,它涉及到对人类情感状态的理解和分析。随着深度学习技术的发展,基于深度学习的人脸表情识别系统因其高精度和强大的特征学习能力而受到广泛关注。本文旨在探讨基于深度学习的人脸表…...
【mongodb】社区版8:改变配置bindip和授权
更改配置 sudo systemctl restart mongod (base) root@k8s-master-pfsrv:/home/zhangbin# sudo tail -n 20 /var/log/mongodb/mongod.log 日志感觉是成功了:{"t":{"$date":"2024-11-19T19:57:47.076+08:00"...
python入门9-函数基础
函数介绍 <1>什么是函数 请看如下代码: print(" _ooOoo_ ") print(" o8888888o ") print(" 88 . 88 ") print(" …...
AMD(Xilinx) FPGA配置Flash大小选择
目录 1 FPGA配置Flash大小的决定因素2 为什么选择的Flash容量大小为最小保证能够完成整个FPGA的配置呢? 1 FPGA配置Flash大小的决定因素 在进行FPGA硬件设计时,选择合适的配置Flash是我们进行硬件设计必须考虑的,那么配置Flash大小的选择由什…...
TypeScript学习笔记(二)
接一 四、类型声明 使用 : 来对变量或函数形参,进行类型声明: let a: string //变量a只能存储字符串 let b: number //变量b只能存储数值 let c: boolean //变量c只能存储布尔值 a hello a 100 //警告:不能将类型“number”分配给类型“…...
Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤
官网:https://www.jenkins.io/ 1 下载 环境准备: 版本支持查询:https://pkg.jenkins.io/redhat-stable/ 安装JDK17:https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...
多目标粒子群优化(Multi-Objective Particle Swarm Optimization, MOPSO)算法
概述 多目标粒子群优化(MOPSO) 是粒子群优化(PSO)的一种扩展,用于解决具有多个目标函数的优化问题。MOPSO的目标是找到一组非支配解(Pareto最优解),这些解在不同目标之间达到平衡。…...
【网络系统管理】2023年全国职业院校技能大赛:组策略--10套题组合--1
1、限制访问C盘; (1)搜索《我的电脑》 (2)用户配置\策略\管理模板\Windows组件\文件资源管理器 2、禁止运行run.exe; (1)搜索《应用程序》 (2)用户配置\策略\管理模板\系统...
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
在现代 Web 开发中,API(特别是 RESTful API)是前后端分离架构的核心。Gin 框架提供了丰富的功能来处理 API 请求和 JSON 数据,使得开发者可以快速构建高效的接口服务。本篇博客将从基础到深入,全面讲解如何使用 Gin 框…...
在Linux下配置gitee与Github的远程仓库
目录 前言 云服务器下载git 检测是否下载成功git Linux下配置gitee远程仓库 代码提交演示 git三板斧 Linux下配置Github远程仓库 最后的提醒 前言 那么本篇文章将是在,你已经创建了本地仓库的基础上,在Linux下配置gitee的远程仓库的步骤ÿ…...
自动化测试过程操作细节
一、软件与框架介绍 1. Postman 读音:[pəʊstmən](剖斯特曼) 介绍:API开发与测试的得力助手,通过直观界面发送HTTP请求,查看响应数据。支持环境变量、集合、脚本等功能。 主要特点:易于使用…...
iic协议
IIC(Inter-Integrated Circuit)协议,也被称为I2C协议,是一种由荷兰的PHILIPS公司(现为NXP半导体公司)开发的简单、高效的通信协议。以下是关于IIC协议的详细介绍: 一、IIC协议概述 定义&#…...
uniapp、js判断输入的内容是整数
清奇的思路 通过取余运算符 % 来检查 输入的内容是否为整数 for (var i 0; i < this.list.length; i) {if (this.list[i].times % 1 ! 0) { // 使用取余运算符检查是否为整数uni.showToast({icon: none,title: 请输入整数的套餐次数,})return;}}...
《Qt Creator:人工智能时代的跨平台开发利器》
《Qt Creator:人工智能时代的跨平台开发利器》 一、Qt Creator 简介(一)功能和优势(二)快捷键与效率提升(三)跨平台支持(四)工具介绍与使用主要特性:使用步骤…...
The Yarn application application_xxx_xxx doesn‘t exist in RM
本文主要解决flink在standalone模式下,flink run却一直使用yarn-session模式的问题。 问题 有个客户找到笔者,问题是报错如下: 分析 笔者先从环境入手,首先要确定的是flink是使用了什么模式。确认过后是使用standalone模式。 那就很奇怪&a…...