手搓一个ChatUI需要分几步
只关注项目代码的同学可以直接跳转目录中的正文部分,查看项目仓库和功能介绍。
引言
Chatbot的UI界面设计,是和传统软件不同的:都是当面一个简洁的对话框,框里预备着热乎的工具,可以随时更新。
像我这样做工的牛马,午休傍晚下了班,每每花几个token,问一两句弱智吧的问题,——这是一年多前的事,现在一个问题都得设计个COT,——不用登录,在主页改改prompt,测完了就发群里刷一下存在感。
倘肯多费点心思,便可以问问3.11和3.9谁大,或者让姥姥念CD-Key哄你睡,姑且当作谈资了。如果充点真金白金,那就能获得一个API-Key,但我们这些牛马,多是白嫖党,大抵没有这样阔绰。只有公司报销的领域专家,才能点进绑定支付方式的页面里,买这买那的,写个脚本直接调用API慢慢跑着测。
我从毕业起,就在IT通信行业当伙计,父母和掌柜都说,不是e人,怕侍候不了VIP客户,就在组里开发开发后端。
公司内的stackholder,虽然容易说话,但是唠唠叨叨缠夹不清的也很不少。他们往往要亲眼看着代码跑起来,看过消息交互的抓包格式对了没有,又亲看将服务器整到shutdown,还能定时恢复,然后放心:在这严重监督之下,出一点小问题也很为难。
所以过了几天,掌柜说这些活太简单了,让去看看AI。幸亏大学里有点底子,也算对口,便改为既要开发后端,又要设计前端,还要兼顾AI算法和应用场景的奇怪职务了。
我从此便每天挂在Github上,看看有什么可以拿来用的App做个Demo。虽然没什么失职,但是总觉有些单调。
有些App太臃肿,npm install跑完就带上了全家;
有些太简单,没法适配微信群里一天更新三回的模型和后端框架。
只有最后狠下心来自己悄悄写一个,取个名就叫Chat-UI,算是勉强满意,所以来说说。
https://github.com/AI-QL/chat-uihttps://github.com/AI-QL/chat-ui
Chat-UI是不需要npm install和run time就能运行的,只需唯一的html单文件。
它身材很小巧;蓝白配色,底部夹杂着一些mdi图标;只有简单的light主题。
用的虽然是VUE,可是只用CDN引入了JS库,简单快捷,而且都是latest版本,似乎不用更新,也不用安装。
<script src="https://cdn.jsdelivr.org/npm/vue/dist/vue.global.prod.min.js"></script><script src="https://cdn.jsdelivr.org/npm/vuetify/dist/vuetify.js"></script><link href="https://cdn.jsdelivr.org/npm/vuetify/dist/vuetify.css" rel="stylesheet">
LLM对人说话,总是满口markdown,教人半懂不懂的。又因为我自己前端开发经验不过关,便直接引入了md-editor-v3,替我可视化markdown。
fetch回来的JSON body刚收到,所有的组件就都看着它笑,有的叫道,
“OpenAI,你又增加新的限制区域了!”它不回答,只是吐出一行,“Fail to fetch XXX”便不再多言。
他们又故意的高声嚷道,“Nidia NIM 都免费提供 Llama 405B 了!”
OpenAI睁大眼睛说,“哪有什么免费的...”
“就是免费的,只要注册时候额外申请一下免费token就行了,随便用。”
OpenAI便涨红了脸,额上的青筋条条绽出,争辩道,“那也是有数量上限的,而且不支持跨域,跨域你懂吗?”接连便是难懂的话,什么“CORS”, 什么“Allow Headers”之类,
引得众后端都哄笑起来:那我再开发一个Proxy不就搞定了吗,workflow内充满了开源的空气。
简单小巧的OpenAI API访问:一键部署,轻松上手-CSDN博客文章浏览阅读1.6k次,点赞62次,收藏16次。OpenAI Proxy Docker项目不仅简单小巧,而且易于上手。通过使用最新的Bun运行时,你可以在保持高性能的同时,得到可靠的代理服务解决方案。https://blog.csdn.net/aiqlcom/article/details/144684140
听人家背地里谈论,OpenAI原来也免费送过5刀的token,但没有境外手机号,又不会绑境外信用卡;于是愈用愈少,弄到将要过期了。幸而开源vllm跑得一手好模型,便换一个模型当后端用用。
可惜OpenAI又传染的一样坏脾气,就是API版本控制。坐不到几天,便连JSON和定义,一齐更新了。如是几次,没有办法,便免不了再开发一个API UI,偶然查看一下最新格式。
https://api-ui.aiql.com/ 第一次登陆比较慢,可以下载html修改CDNhttps://api-ui.aiql.com/
但是OpenAI在我们这里,品行比别家都好,格式支持的最全,报错最详细;虽然间或没有在文档里更新,暂时记在Issue里,但不出一月,定然修复,从Issue里done掉了名字。
OpenAI融了几回资,涨红的股价渐渐走了高,旁人便又问道,“OpenAI,AGI当真有出路么”,OpenAI看着问他的人,显出不屑置辩的神气。
他们便接着说道,“你怎的连半个开源的模型也没有呢?”OpenAI立刻显出颓唐不安模样,脸上笼上了一层灰色,嘴里说些话;这回可是全是金鍂鑫𨰻之类,一下全懂了。在这时候,众人也都哄笑起来:workflow内充满了闭源的空气。
在这些时候,我可以附和着challenge,掌柜是决不责备的。而且掌柜见了那些用OpenAI模型的项目,也每每这样发难,引人发笑。
OpenAI自己知道不能开源,便只好向各方面发力。有一回对我发邮件,“你知道多模态和Function call么?”
我略略点一点头。
他说,“用过,……我便要考你一考。request里的messages,怎样写的?”
我想,API文档里都写着的,也配考我么? 便回过脸去,不再理会。
OpenAI等了许久,很恳切的说道,“不会用吧?……我教给你,记着!这些format应该记着。将来做掌柜的时候,装逼要用。”
我暗想我和掌柜的等级还很远呢,而且我们掌柜也从不看开发细节;又好笑,又不耐烦,懒懒的答他道,
“谁要你教,不就是content里面一个string么?”OpenAI显出极高兴的样子,将一个长长的schema敲着我的脑袋,点头说,“对呀对呀!……messages光是role就有六样写法,你知道么?”我愈不耐烦了,努着嘴走远。
OpenAI刚写了个oneOf,想在后面跟上[developer, system, user, assistent, tool, function],见我毫不热心,便又叹一口气,显出极惋惜的样子, 把function标为了deprecated,然后又把user和tool定义了不一样的content parts。
(user, assistent, tool 里面的支持格式其实不一样哟)
有几回,隔壁开发组见得着KPI,也赶热闹,围住了OpenAI。它便给他们模型吃,一周一更新。开发组从年初加班到年尾,仍然不散,眼睛都望着array里不断新增的 [o1, o1-2024-12-17, o1-preview, o1-preview-2024-09-12, o1-mini, o1-mini-2024-09-12, gpt-4o, gpt-4o-2024-11-20, gpt-4o-2024-08-06, gpt-4o-2024-05-13, gpt-4o-audio-preview, gpt-4o-audio-preview-2024-10-01, gpt-4o-audio-preview-2024-12-17, gpt-4o-mini-audio-preview, gpt-4o-mini-audio-preview-2024-12-17, chatgpt-4o-latest, gpt-4o-mini, gpt-4o-mini-2024-07-18, gpt-4-turbo, gpt-4-turbo-2024-04-09, gpt-4-0125-preview, gpt-4-turbo-preview, gpt-4-1106-preview, gpt-4-vision-preview, gpt-4, gpt-4-0314, gpt-4-0613, gpt-4-32k, gpt-4-32k-0314, gpt-4-32k-0613, gpt-3.5-turbo, gpt-3.5-turbo-16k, gpt-3.5-turbo-0301, gpt-3.5-turbo-0613, gpt-3.5-turbo-1106, gpt-3.5-turbo-0125, gpt-3.5-turbo-16k-0613]。
OpenAI着了慌,伸开五指将文档罩住,弯腰下去说道,“不多了,我已经不多了。”直起身又看一看股价,自己摇头说,“不多不多!多乎哉?不多也。”于是这一群Prompt Engineer都在哭声里走散了。
OpenAI是这样的使人快活,可是没有他,别人也便这么过。vllm,TGI,部署个小模型当后端也不是不能用。
https://github.com/huggingface/text-generation-inferencehttps://github.com/huggingface/text-generation-inferencehttps://github.com/vllm-project/vllm
https://github.com/vllm-project/vllm
谁曾想TGI基于conda,而这玩意license不能给大组织商用:
我知道AI多半是个杀猪盘,但是没曾想,屠夫和刀子都没动手,甚至猪还没哼哼,砧板第一个跳起来给了我一巴掌:
Anaconda 许可变更解读https://www.datacamp.com/blog/navigating-anaconda-licensing
有一天,大约是2024年圣诞前的两三天,掌柜正在慢慢的定OKR,取下粉板,忽然说,“OpenAI长久没有新东西了。”我才也觉得它的确长久没啥新闻了。
一个带着黑眼圈的人说道,“它怎么没更新? ……他o1-pro了。”
掌柜说,“哦!”
“它总仍旧是更新。这一回,是自己卷,竟连更12天。它家的新东西,200刀一个月,还只能Web访问,用得起么?”
“后来怎么样?”“怎么样?先充钱,后来是封号,信用卡记录被老婆看到了,再打折了腿。”
“后来呢?”“后来打折了腿了。”
“打折了怎样呢?”“怎样?……谁晓得?许是换用Llama了。”掌柜也不再问,仍然慢慢的算他的帐。
圣诞过后,东北风是一天凉比一天,看看将近元旦;
我整天的靠着AI的火,也须换开源模型了。
clone了一整天的模型,没有一个能用的,我正合了眼坐着。忽然间听得一个声音,“试试这MOE吧。”
这声音虽然极低,却很耳熟。看时又全没有人。站起来向外一望,竟是Deepseek在微信群里悄悄发着自己的照片:
它脸上全是benchmark,已经看不出原本的样子;穿一件自研的大衣,盘着两腿,下面垫一个MOE,用草绳在肩上挂住;见了我,又说道,“试一试MOE吧。”
掌柜也伸出头去,一面说,“新的开源模型么?训练成本才557.6万美元呢!”
Deepseek很疲惫的仰面答道,“这,v3不算新模型了……已经超过Llama 405B了。也赶上GPT-4o了,性能算好的了。”
掌柜仍然同平常一样,笑着对我说,“你看,又多了一个连部署都部署不起的模型”。但Deepseek这回却不十分分辩,单说了一句“我在Huggingface上开源了!”
“开源? 那要不我们试试?支持Function call吗” Deepseek低声说道,“支持,支,早就支持了……”他的眼色,很像恳求我,不要再细问(问就是官方文档更新慢)。
此时已经聚集了几个开发,便去查看文档了。我重新配置了Chat-UI,清空对话记录,重置了MCP server。他从新人注册里面摸出了一个月的免费token,放在我手里,见他满手都是卡,也不知是哪个哥布林洞穴里来的,想必模型便是用这2000张卡炼出来。不一会,我们调通了代码,他便又在旁人的说笑声中,去下一个交流群里了。
自此以后,就没有再看其他模型了。到了年底,掌柜取下粉板说,“还有Llama 3.3呢!”到了第二天的中午,又说,“Mistral最近有更新么?”到第三天又问,“Qwen是不是也在推新模型”,于是我狠狠心,把这些都用vllm测了一遍。
我到现在终于差不多可以确定Chat-UI大概可以拿出来给大家用一用了。
https://github.com/AI-QL/chat-ui 帮忙点个赞吧https://github.com/AI-QL/chat-ui
正文
其实要把一个项目说清楚,一篇短文或者回答是不够的。
然而我这人又不善言辞,只好自欺欺人:“一个纯粹的前端项目,不需要用复杂的介绍来丰富的,交互逻辑清晰,满足基本功能需求,就可以了。“
所以这里只是估摸着说一下基本的功能,具体的代码解读,等有时间再做吧。
配置
我开发部署后端的时候,经常头疼没有一个前端可以用,主要是后端的URL和model名称一直在变,有时候又需要给别人展示,直接curl太粗暴了,所以Chat-UI里可以随意配置URL,还可以通过Json文件快速导入写好的配置:
Prompts
支持插入多个prompts,会在messages里面帮你合并一起放到system role对应的text content里。这样可以测试不同提示词以及顺序对模型的影响。暂时用不上的,但是已经写好的prompt,可以放到backup里,随时拖拽交换对比。
MD格式支持
可以支持Markdown语法显示,比如Mermaid图和代码块:
同时也可以一键复制文本,或者显示原始文本。
历史记录
记录聊天历史,可以点击载入,或者下载并保存为Json文件,也可以单独或批量删除。
多模态
可以支持图片多模态,记得选择后端模型的时候要选择vision模型,比如Llama vision或者Pixtral。
i18n
提供基本的多语言支持,选了5种特殊字符比较多的语言,有需要的同学可以自己加
MCP
可以作为渲染端对接 MCP(Model Context Protocol)Servers,具体参考另一个项目:
MCP(Model Context Protocol)模型上下文协议 实战篇1_mcp协议内容-CSDN博客文章浏览阅读2.6k次,点赞70次,收藏10次。MCP 协议(Model Context Protocol)模型上下文协议,简单实战,快速开发一个AI Agent APP_mcp协议内容https://ai-ql.blog.csdn.net/article/details/144324496
这样可以扩展更多agent功能以及function call
Response兼容
对于一些正常OpenAI SDK兼容的后端都可以支持。对于一些特殊后端,比如Cloudflare的 Workers AI (如下这种Rest API定义):
{"result": {"response": "Hello, World first appeared in 1974 at Bell Labs when Brian Kernighan included it in the C programming language example. It became widely used as a basic test program due to simplicity and clarity. It represents an inviting greeting from a program to the world."},"success": true,"errors": [],"messages": []
}
或者python写的直接plain text返回的response,也都可以兼容(是的,真的有这样的后端,除非自己写一个不然真的找不到能支持这种离谱格式的玩意)。
也可以勾选支持流式输出(stream)。
Cloudflare Pages
项目比较简单,直接fork之后可以部署在自己的域名下,如果不熟悉Cloudflare pages请查看链接:
https://developers.cloudflare.com/pageshttps://developers.cloudflare.com/pages
Docker
也提供直接Docker部署的镜像:
Docker Image - AIQL/Chat-UIhttps://hub.docker.com/repository/docker/aiql/chat-ui/tags?page=1&ordering=last_updated
既然有了镜像,所以默认可以支持其他容器化部署,比如K8s,或者在Huggingface上直接一行代码搞定:
From aiql/chat-ui
https://huggingface.co/spaces/AI-QL/chat-uihttps://huggingface.co/spaces/AI-QL/chat-ui
这里也提供一个例子。
HTML
最后,也是最推荐的用法,可以直接在Github上下载 index.html,双击打开即可,不用安装也不用run。
https://github.com/AI-QL/chat-uihttps://github.com/AI-QL/chat-ui所有代码和部署教程已经同步至 GitHub 仓库,如果觉得项目对你有帮助,欢迎点个 ⭐️ 支持,非常感谢!
相关文章:

手搓一个ChatUI需要分几步
只关注项目代码的同学可以直接跳转目录中的正文部分,查看项目仓库和功能介绍。 引言 Chatbot的UI界面设计,是和传统软件不同的:都是当面一个简洁的对话框,框里预备着热乎的工具,可以随时更新。 像我这样做工的牛马&a…...

2024年年度总结
前言 前一段时间,看到网上有人发类似于年度总结的东西,我想我也可以写一个,今年的日记也是从开头一直贯彻到了结尾 回忆起一年的事情还是有些困难 一月 回忆起有点困难,原因是我的日记大部分都是记录我当天地感想与情绪&#x…...

labelme2yolov8-seg 草稿()
简介: 最近做实例分割分割,使用Labelme生成json格式标签后,需要转换为txt标签,才能供YOLO进行训练。 在参看b站,github后,发现GitHub有相关项目:lableme2yolo 一个是ultralyics官方的JSON2YO…...

开源简史与概览
Think 1.论述“自由软件”与“开源软件”的区别与联系? 2.GitHub Trending 是一个能够快速找到有趣的新项目的地方;而 OpenLeaderboard 也是一个能够发现有趣而有影响力项目的地方。尝试从这两个网站中找到感兴趣的若干项目,挖掘并分析出上…...

充电桩语音提示芯片方案-支持平台自定义语音NV128H让充电更便捷
随着工业化与城市化进程的加速推进,传统燃油汽车的数量急剧攀升,这直接导致了石油资源的过度开采与消耗。石油,作为不可再生的化石燃料,其储量日益枯竭,价格波动频繁,给全球能源安全带来了前所未有的挑战。…...

277-基于八路256Ksps 24bit AD生物电震动检测FMC子卡
一、板卡概述 板卡基于AD7768 AD芯片设计的八路低速采集的FMC 子卡,支持直流耦合,产品应用于生物电、脑电波、声音,震动等信号采集。 二、板卡参数及性能 板卡功能 参数 内容 ADC 芯片型号 AD7768 路数 8路ADC, 采样率 2…...
【电路理论四】正弦电流电路
正弦电流 正弦量是随时间按正弦规律变动的电路变量。 随时间按正弦规律变动的电流称为正弦电流。 正弦电流的瞬时值表达式: 称为正弦电流的三要素。 分别为振幅/幅值,角频率,初相。 幅值为正弦电流的最大值,恒为正。 为正弦电…...

【PyCharm】如何把本地整个项目同步到服务器?
在PyCharm中,您可以使用部署功能将项目同步到服务器。以下是步骤和示例配置: 打开PyCharm,选择您的项目。 点击菜单栏的 “File” -> “Settings” -> “Build, Execution, Deployment”。 在左侧菜单中,选择 “Deployme…...

露营小程序搭建有哪些步骤?小程序里面可以找个露营搭子
露营不仅仅是走进大自然的旅程,它也成为了一种社交和体验式的活动。随着小程序的普及,露营活动也越来越多地开始在线上开展。通过搭建一个露营小程序,商家不仅可以为用户提供更多的露营选择,还可以帮助他们找到合适的露营搭子。那…...

SOLID-开闭原则
单一职责原则:https://blog.csdn.net/dmk877/article/details/143447010 在前面我们学习了单一职责原则,今天来一起学习一下SOLID原则中的开闭原则(Open-Closed Principle, OCP) 通过本篇博客你将学到到以下内容 ①什么是开闭原则 ②如何实现开闭原则 ③…...

前端经典面试合集(二)——Vue/React/Node/工程化工具/计算机网络
1. 说说 Vue 中的 Diff 算法 Vue 的 Diff 算法 主要用于优化虚拟 DOM 和实际 DOM 之间的比较过程。它通过以下几种策略来提高性能: 最小化对 DOM 的操作:Vue 通过在内存中构建一个虚拟 DOM 树,在虚拟 DOM 树与真实 DOM 树之间进行比较和更新…...

PH47代码框架 24241231 重要更新
仪式感一下:2024年最后一天,发布 PH47 代码框架的一次重要更新。当然这并不是有意的,而是直到现在才把更新的所有工作全部做完(希望确实如此)。 本次更新要点: 1、加入多IMU支持。本次更新正式加入对 MPU65…...

Qt6之QML——作用域
作用域定义了表达式可以访问哪些变量、属性或对象,并决定了在变量重名时的优先级如何处理。以下将从作用、绑定、组件作用域和使用技巧四个方面详细解析 QML 中的作用域。 1. 作用:表达式的变量访问与优先级 在 QML 中,表达式能够访问的变量…...

119.【C语言】数据结构之快速排序(调用库函数)
目录 1.C语言快速排序的库函数 1.使用qsort函数前先包含头文件 2.qsort的四个参数 3.qsort函数使用 对int类型的数据排序 运行结果 对char类型的数据排序 运行结果 对浮点型数据排序 运行结果 2.题外话:函数名的本质 1.C语言快速排序的库函数 cplusplus网的介绍 ht…...

C#封送类
封送类(Marshaling classes)在.NET框架中扮演着至关重要的角色,尤其是在托管代码与非托管代码之间进行数据交换时。封送过程涉及到将托管环境中的对象转换为非托管环境中可以理解的形式,并且反之亦然。这一过程确保了两种不同类型…...

2024年度学习总结
2024年是我学业生涯的结束,是我职业生涯的开始。2024年6月19日我顺利研究生毕业,进入体制内,陆止于此,海始于斯,知识和文化最大的魅力,大概就是教会人谦卑和敬畏。读研的目的不是为了单纯拿到哪个证书&…...

我的博客年度之旅:感恩、成长与展望
目录 感恩有你 技能满点 新年新征程 嘿,各位技术大佬、数码潮咖还有屏幕前超爱学习的小伙伴们!当新年的钟声即将敲响,我们站在时光的交汇点上,回首过往,满心感慨;展望未来,豪情满怀。过去的这…...

undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12
目录 我的解决方法: 测试: 报错: undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12 from torch._C import * # noqa: F403 ImportError: /mnt/pfs/users/lbg/envs/mmpano/lib/python3.9/site-packages/torch/lib…...

【OTA】论文笔记--《智能网联汽车整车OTA功能设计研究》智能网联汽车OTA系统设计分析报告
智能网联汽车OTA系统设计分析报告 引言 随着汽车智能化、网联化水平不断提升,现代汽车中电子控制单元(ECU)的数量和复杂度持续增加。据统计,高级轿车上电子电气元件的成本已占整车开发成本的60%~70%。为了实现对这些电控单元的软件开发调试、数据标定、文件更新和故障修复,…...

c#String和StringBuilder
目录 一,String 1,string的特点: 2,string常用方法 (1)Length (2)Substring() (3)ToUpper() (4)ToLower() (5&…...

【Linux】HTTP协议
之前,我们已经做过了自定义协议,事实上,已经有很多现成已经做好又非常好用的协议,它们都是相同的,比如HTTP协议。所谓HTTP协议,就是超文本传输协议,定义了客户端和服务器之间是如何通信的&#…...

计算机网络 (14)数字传输系统
一、定义与原理 数字传输系统,顾名思义,是一种将连续变化的模拟信号转换为离散的数字信号,并通过适当的传输媒介进行传递的系统。在数字传输系统中,信息被编码成一系列的二进制数字,即0和1,这些数字序列能够…...

《向量数据库指南》——Milvus Cloud 2.5:Sparse-BM25引领全文检索新时代
Milvus Cloud BM25:重塑全文检索的未来 在最新的Milvus Cloud 2.5版本中,我们自豪地引入了“全新”的全文检索能力,这一创新不仅巩固了Milvus Cloud在向量数据库领域的领先地位,更为用户提供了前所未有的灵活性和效率。作为大禹智库的向量数据库高级研究员,以及《向量数据…...

Unity3D 网络框架设计详解
前言 Unity3D是一款强大的跨平台游戏开发引擎,网络框架的设计对于实现客户端与服务器之间的稳定通信至关重要。本文将详细介绍Unity3D网络框架的设计原理、技术要点以及代码实现。 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一…...

网络渗透测试实验四:CTF实践
1.实验目的和要求 实验目的:通过对目标靶机的渗透过程,了解CTF竞赛模式,理解CTF涵盖的知识范围,如MISC、PPC、WEB等,通过实践,加强团队协作能力,掌握初步CTF实战能力及信息收集能力。熟悉网络扫描、探测HTTP web服务、目录枚举、提权、图像信息提取、密码破解等相关工具…...

Wend看源码-Java-Collections 工具集学习
摘要 java.util.Collections它提供了一系列静态方法,用于对集合(如List、Set、Map等)进行操作。这些操作包括排序、查找、替换、同步等多种功能,帮助开发者更方便地处理集合数据。以下是Collections 提供的一些主要方法的总结。…...

[JAVA]MyLogger
import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.*;/*** 可以自已定义日志打印格式,这样看起来比较方便些**/ class MyFormatter extends Formatter {Overridepublic String format(LogRecord ar…...

玩转OCR | 腾讯云智能结构化OCR初次体验
目录 一、什么是OCR(需要了解) 二、产品概述与核心优势 产品概述 智能结构化能做什么 举例说明(选看) 1、物流单据识别 2、常见证件识别 3、票据单据识别 4、行业材料识别 三、产品特性 高精度 泛化性 易用性 四、…...

记一次 dockerfile 的循环依赖错误
文章目录 1. 写在最前面1.1 具体循环依赖的例子 2. 报错的位置2.1 代码快速分析2.2 代码总结2.3 关于 parser 的记录 3. 碎碎念 1. 写在最前面 笔者在使用 dockerfile 多阶段构建的功能时,写出了一个「circular dependency detected on stage: xx」的错误。 解决方…...

Trimble天宝X9三维扫描仪为建筑外墙检测提供了全新的解决方案【沪敖3D】
随着城市化进程的快速推进,城市高层建筑不断增多,对建筑质量的要求也在不断提高。建筑外墙检测,如平整度和垂直度检测,是衡量建筑质量的重要指标之一。传统人工检测方法不仅操作繁琐、效率低下,还难以全面反映墙体的真…...