2026年1月

当 AI 长出身体,从能听会说到能看会动!Agora Convo AI World 拉斯维加斯之夜活动回顾

主笔:周森

审校:小炫

编辑:陈述

AI 不再仅仅是屏幕里的对话框,从能感知情绪的陪护机器人,到具备实时翻译能力的智能眼镜,AI 硬件化成为 CES 2026 呈现的重要趋势。

然而,在 AI 硬件热潮背后,行业也在迫切寻找一个答案:当 AI 试图长出「身体」,它需要怎样的底层架构与交互逻辑?

1 月 9 日晚,Agora(声网兄弟公司)联合 RiseLink(博通集成)在拉斯维加斯 The LOFT at Cabo Wabo Cantina 举办了 Convo AI World 论坛活动。

这场吸引了近 300 位全球科技精英参与的盛会,意在为这股 AI 硬件热潮指引风向。

两家企业不仅联合发布了基于 BK7259 芯片的 R2 全场景 AI 机器人开发套件,更首次系统性地提出了「物理 AI 的蓝图」。

△ 活动现场

具身 AI 的蓝图:从「工具」到「生命形态」

当前,行业正处于从文本模型、语音助手,迈向具备长期记忆、情绪理解与陪伴能力的 AI 伙伴的早期阶段。

Physical AI,本质上是具身智能(Embodied AI) 在消费级市场的落地呈现。AI 硬件不再是冰冷的电子零件,而是一种正在形成的数字生命形态。

由 Agora 与 RiseLink 联合提出的 Physical AI 蓝图,则试图为下一阶段的具身智能发展提供一套以体验为核心的设计方法论。

Tony Wang 在演讲中强调,Physical AI 的关键不在于堆砌硬件参数,而在于对话体验,即在复杂环境中理解语境、识别说话者并感知情绪的能力。

未来,AI 的核心语言将从单向的「指令」彻底转变为双向的「对话」,其商业模式也将从硬件单次销售,转向以订阅制为核心的长期服务。


△ 发言嘉宾:Tony Wang,Agora 联合创始人兼 CRO

张鹏飞博士进一步阐述道,Physical AI 时代的竞争已演变为协同效率的竞争。想要成为或持续保持第一,前提是与各自领域中已经处于领先位置的伙伴深度协作。

RiseLink 将通信、算力与功耗管理深度整合,配合 Agora 的 RTC 实时互动能力,构成了 Physical AI 的基础引擎:以低延迟保障交互的自然性,以高能效支撑长时间的在线陪伴。

△ 发言嘉宾:张鹏飞博士,RiseLink(博通集成) CEO

真实的 AI 堆栈:重构技术底层

当 AI 跨越数字边界、从云端软件形态进入物理硬件,底层的技术架构不应该只是「模型 + 数据 + 算力」,而需要从「原子」到「比特」实现闭环。

在论坛环节,嘉宾们探讨和回答了什么是「真实的 AI 堆栈」并达成共识:AI 是否好用,取决于设备能否通过物理感知快速理解语境并做出即时反应。

△ Panel: The Real AI Stack

圆桌主持人:Rin Yunis 博士,RiseLink 开发者体验负责人 (中)

圆桌嘉宾: (自左向右)

  • Max Fillin, WowCube CEO
  • Blake Margraff, Healthcare Technology 创始人
  • Amir Eitan, Nanit CPO
  • Lin Chen 博士, Wyze 首席科学家

在架构选择上,边缘(Edge)与云端(Cloud)的分工不再是二选一,而是基于延迟、隐私和成本的精密平衡 。对实时性和隐私敏感的能力更适合本地运行,而需要持续迭代、受成本约束的功能则更适合放在云端,工程实践应从验证出发,再逐步优化边云分配。

在消费级场景中,成本是最硬的约束条件。无论技术听起来多么具有颠覆性,如果缺乏可持续的单位经济模型(Unit Economics),产品终究无法走出实验室成为长期的生意。

同时,嘉宾们达成了一个感性却深刻的共识:AI 必须具备稳定的记忆和一致的行为 。一个今天热情、明天健忘的 AI 硬件,是无法真正建立起用户信任的。

△ 圆桌嘉宾:Max Fillin, WOWcube CEO(左)

这种信任的建立,在家庭与健康等强私密场景下尤为微妙。品牌的真实投入与清晰的价值传递,远比罗列一堆天衣无缝的安全技术术语更有效。 用户对 Physical AI 的接受度,往往并不取决于你背书了多少项加密协议,而取决于极其直观的交互体感,即:反馈要即时(低延迟)、过程要透明(可解释)、底线要有人守(人类参与)。

△ 圆桌嘉宾:Lin Chen 博士, Wyze 首席科学家

应用与具身落地:AI 硬件的场景爆发

Physical AI 最令人兴奋的特质在于它的多模态能力,以及在各个场景的迅速渗透。

△ WOWcube(左):将经典的 2x2 魔方形态与 24 个高分辨率屏幕相结合,通过扭转、倾斜和触觉交互,让玩家在立体的物理空间中体验沉浸式的游戏与应用。

△ Wyze(右上): 新款户外安防摄像头采用贴纸式安装方式固定在窗户上,可从室内进行户外录像

△ Nanit Pro(右下): 全功能婴儿监控系统,新增用于记录宝宝成长发育的功能

在医疗与健康领域,Physical AI 的价值在于它能实时处理复杂的生理信号,并以人类能理解、能接受的方式进行交互,从而在专业性与亲和力之间找到平衡。

Blake Margraff 指出,AI 在医疗中的落地绝非简单的自动化,而是要实现「自动化的患者监测与干预」。

△ 圆桌嘉宾:Blake Margraff,Healthcare Technology 创始人

Amir Eitan 则从育儿与家庭监测的角度补充道,真正的信任来自于 AI 能在特定场景下提供「可解释的反馈」。

△ 圆桌嘉宾:Amir Eitan,Nanit CPO

在 AI 陪伴的主题论坛中,各位嘉宾围绕 AI 陪伴产品在儿童与家庭场景中的实际落地展开话题。

△ Panel:Where AI Companionship Comes to Life

圆桌主持人:Patrick Ferriter,Agora 产品与市场高级副总裁(左下)

圆桌嘉宾:

  • 孙兆治,珞博智能 CEO(左上)
  • Angela Qian,灵宇宙 Luka AI 战略负责人 (右上)
  • Wayne Zhang, Dify Chief of Staff(右中)
  • Margo Wang,Lgenie &灵机一动 Agent 市场总监(右下)

稳定性和一致性是影响儿童用户对 AI 硬件接受度的关键因素。无论是故事内容、角色设定还是互动方式,一旦发生变化,都会显著影响使用体验。

低延迟是实时陪伴场景中的基本要求,是建立用户与产品情感连接的底线,响应过慢会直接削弱互动的自然感。

长期留存更具挑战性。吸引用户首次尝试与长期留存两者的差异性需要引起重视,长期留存更具挑战性,需要 AI 在持续使用中形成稳定的互动节奏和情感连接,而不仅是单次回应。

安全与责任方面需要引入多层防护思路,包括年龄匹配内容、实时干预机制、以及对儿童隐私的明确告知与限制。当 AI 承担陪伴角色时,如何在维持互动亲密性的同时设立清晰边界,仍是行业需要持续面对的问题。

△ Fuzozo 芙崽(左上):面向 Z 世代的 AI 养成系潮玩

△ Luka AI Cube(右上):灵宇宙小方机,儿童 AI 学伴

△ Lgenie (左下):小匠宠物陪伴小车 & 四足桌面机器人

△ 海马爸比(右下): AI 智能婴儿看护器

在产品演示环节,Diana Zhu 博士主持发布了 Choochoo AI 教育机器人。她提到,Choochoo 能够实现流畅的视觉与动作反馈,核心在于集成了 RiseLink 的高集成度 SoC 方案。该芯片在单颗硅片上整合了 Wi-Fi 连接、音视频处理与 AI 加速引擎,使得开发者能够绕过复杂的底层硬件调优,直接在 R2 套件上通过简单的 API 调用,实现原本需要高性能服务器才能支撑的「视觉-语言-动作」协同。

△ 发言嘉宾:Diana Zhu 博士,RiseLink 美国负责人

作为首款由 RiseLink 芯片与 Agora 对话式 AI 引擎深度驱动的教育机器人,Choochoo 不仅能听懂孩子的提问,更能通过视觉传感器「看」到周围的环境与孩子的动作,并做出相应的物理反馈。

△ Choochoo / 延伸阅读:对话式 AI 升级,不仅能看还能动

值得一提的是,作为 R2 全场景 AI 机器人开发套件标杆案例,陆吾智能旗下的桌面机器人「陆卡卡」也同步亮相。现场,陆卡卡展示了如何在紧凑的形态下实现高频、低延迟的 AI 交互。

△ 陆卡卡 / 延伸阅读:桌宠陆卡卡,一只「兵蚁」从二次元走进现实

在两款极具代表性的具身智能产品身上,我们看到,当 AI 拥有了强大的「大脑」(大模型)与灵敏的「身体」后,交互的边界已彻底被打破。两款产品的发布,共同定义了 AI 硬件的新高度,同时也标志着基于 Agora 与 RiseLink 合作的 AI 方案已经完全成熟。

在快闪分享环节,Joey Jiang 分享了打造 AI 原生硬件的最短路径,强调了模块化硬件对快速实现概念落地的意义。他指出,AI 原生硬件的开发不应再遵循「从零打样」的旧逻辑。通过 Seeed Studio 提供的模块化感知节点(如传感器、视觉模块)与 RiseLink 方案的即插即用式结合,硬件原型的验证周期可以从数月缩短至几周。这种「搭积木」式的开发模式,正是初创团队在 Physical AI 浪潮中抢占市场窗口期的最短路径。


△ 发言嘉宾:Joey Jiang,Seeed Studio 销售副总裁

Kim Jin 分享了打造糯宝 AI 机器人的背后故事。在研发背后,团队耗费大量精力对用户意图的深度理解。通过多模态感知,敏锐地捕捉视觉、触觉与语音背后的感性信息,实现拟人化的回复。这种交互不只是指令的执行,而是基于对用户意图的精准洞察,让机器人产生真实的「情感共鸣」。这标志着 Physical AI 真正跨越了工具属性,进化为懂得用户灵魂的情感伴侣。

△ Pophie (机器灵动) 产品负责人 Kim Jin

△ Maxevis(左):迈威儿童拍学机

△ Pophie 糯宝(右):桌面级情感陪伴机器人

隐私、授权与信任:环境式 AI 的底线

随着环境式 AI(Ambient AI)走向「始终在线」,隐私与信任已不再是合规问题,而是产品体验本身。用户真正担心的并非模型出错,而是设备在「不被察觉的情况下」收集和使用数据。

△ Panel:When AI Is Everywhere: Redefining Data Privacy, Consent, and Trust

圆桌主持人:Ramana Kapavarapu,Agora 首席信息安全官 (CISO) & IT 运营负责人(中)

圆桌嘉宾:(自左向右)

  • Diana Zhu 博士,RiseLink 美国负责人
  • Joe Tham,Ellie 海马爸比联合创始人
  • Gibran Mourani,MiniMax 全球客户经理
  • 卜峥,Kaamel AI 联合创始人兼 CEO

△ 成立于 2021 年底的 MiniMax 刚刚宣布港股上市,成为从成立到 IPO 用时最短的 AI 公司。大家首先向 MiniMax 的 Gibran Mourani 道贺。

围绕隐私实践,嘉宾们形成了一个明确共识:说到做到、做到可见。

透明性: 相比冗长的隐私条款,产品应在交互层面清晰呈现系统是否在监听、收集了什么数据,以及用户如何即时控制这些行为。透明性体现在硬件指示、软件状态和使用流程中,比如用物理指示灯直观地告诉用户系统是否在监听。

边缘保护: 通过边缘计算最小化数据流动,让原始语音和视觉数据停留在本地,是保护隐私的最有效路径。对多数场景而言,无需上传云端、本地处理并仅传递必要信号,既有助于隐私保护,也降低了系统暴露面。

响应机制: 谈及安全事件响应,需要成熟、结构化的应对机制,而非临时决策。快速隔离、明确影响、及时修复与复盘改进,比短期业务考量更重要。过往大型数据泄露案例反复证明,延迟或回避只会放大长期损失。

真正可规模化的信任,来自硬件与软件的一致设计以及可实时验证的控制能力。认证和合规是基础,但只有当系统行为与承诺持续一致,用户对「无处不在的 AI」才会产生长期接受度。

△ 活动现场

AI 具身化不可挡!

纵观整场活动,我们可以从三个层面理解这场关于 Physical AI 的深刻变革:

技术本质: 从「挂载」到「具身」。 AI 不再是硬件外挂的一个功能,而是通过专用芯片和实时通讯协议,深度融合进硬件的神经系统。

交互范式: 从「指令」到「共生」。 当 AI 能够理解语境、感知情绪并拥有长期记忆,它就从一个「好用的工具」进化为一个「理解你的物种」。对话不再是手段,而是其存在的形式。

商业本质: 从「买断」到「订阅」。 物理 AI 的核心价值在于其随时间不断进化的能力。厂商卖出的不再是零件,而是长期的服务与情感陪伴。

在 Agora 和 Riselink 两家公司和来自人工智能、芯片和硬件、AI 算法,以及数字健康、家居安防、AI 陪伴和教育等领域的数十家 AI 软硬件企业代表和顶尖专家的背书下,AI 将跳出单纯的数字世界,开始在物理世界中,真正长出它的身体。■

阅读更多 Voice Agent 学习笔记:了解最懂 AI 语音的头脑都在思考什么

程序一、基础工程资料规划建档:

一个制造产业能否透过实施ERP全面电算化整合信息管理系统,而使企业能够具备:明确化、合理化、高效化、规范化、精细化、自动化的优质管理体系,第一个关键性的问题就是要对整个产业的基础工程做正确而合理的规划。

因为一个产业的基础工程规划建立就有如一栋大楼的地基规划建立一样重要,没有良好稳固的基础,就不可能建立一个具备高效而优质管理体系的企业。

一个制造产业在实施ERP全面电算化整合信息管理系统时必须先规划建立的基础工程包括哪些项目?

我们分别先列示如下,并且一一加以详细说明:

1、集团公司组织规划建档:

当一个企业已经发展成为集团企业之时,规模越大者或跨国际经营者,其经营管理体系的复杂度远比单一公司要超过十倍以上。面对这种大型集团企业的ERP全面电算化整合信息管理系统的规划实施,首先就要把整个集团公司的母子公司组织关系规划建档完成,包括:每个公司的代码、名称(本国名称/英文名称)、资本额、持股比率、公司所在地区/国家、地址、网址、ERP数据库的网址、重要主管资料、使用系统代码、产生单据代码等,并且可以从公司组织表查看到每一家公司的从属关系。

将来整个集团公司的运筹管理资料数据彙总,都会透过这份公司组织表建立的相关数据做为依据,包括:财务运筹管理、营业运筹管理、存货运筹管理、采购运筹管理、人力资源运筹管理、产品研发运筹管理等体系。

通常一个集团企业可以发展到100个母子公司以上已经不多见了,像荷兰的Philips飞利浦集团或美国的GE通用集团,子公司号称超过1000家,在母子公司编码的技术上,都还不会产生重大困扰。我们建议对于关系企业的公司编码上,和客户编码/厂商编码采用相同的编码规则,这样是一劳永逸的办法。即:

(a)、对于国内使用中文的公司,直接以公司名称的前四个中文字的罗马拼音的第一码,4码以后则用流水码,可避免前4码重复。至于流水码要用几码,要看往来客户和厂商的家数多少来决定,最多可以用到4个流水码。

(b)、对于国外非使用中文名称的公司,则直接使用其英文名称的前四码,再加上流水码,将来就可以简单的进行查询的作业。

2、厂别/营所规划建档:

厂别/营所/分公司和母子公司的关系完全不同,母子公司是指两者都同时具备独立的法人资格,都必须独立向政府的税务机关报税的不同公司。而厂别/营所/分公司是指:在同一个公司名称法人之下,有多个制造工厂,多个营业所,或多个分公司,在申报企业之营利事业财务报表和所得税时,必须合并所有厂别/营所/分公司的数据,再统一向总公司所在地点的税捐机关申报。

对于每一个工厂/营所/分公司,都必须分别编定一个代码加以区别,因为厂别/营所/分公司和部门组织和部门代码并不相同,如果公司需要获得每一个厂别/营所/分公司经营的损益分析,就必须把厂别/营所/分公司加以编码管理。

厂别/营所/分公司的编码规则,最好就直接使用2码地区码,加上厂别流水码及属性即可。例如:昆山一厂:KS01F,东莞二厂:DG02F,其中“F”代表工厂(Factory);上海营一所(或分公司):SH01B,大连营二所(或分公司):DL02B,其中“B”代表营业所或分公司(Branch)。如果营业所超过1000家,就用4位流水码,肯定够用。

3、事业部别代码规划建档:

当一个企业跨产业经营的时候,就会用到事业部的管理技术和观念。事业部的观念和母子公司不同,也和厂别/营所的观念不同,事业部是以不同的产业做为区分的依据,例如:通讯事业部、计算机事业部、家电事业部、纺织事业部、包装事业部、化工事业部、家具事业部、汽车事业部等。对于相同的产业事业部可以再以不同的产品类别加以区分管理:例如:家电事业部之下,还可以再分为:洗衣机类、冰箱类、果汁机类、暖气机类、冷气机类、电视机类等产品类别。相同的产品类别再区分为不同的机型,或不同的产品型号,最底层则是每一项产品编号,即,一种产品型号可以依据客户的要求而衍生成为多项不同的产品编号。

部分企业因为规模并没有大到跨越多种产业别,而是以不同的产品类别当做一个事业部来规划管理,当然也可以。万一有一天企业突然快速发展之时,再来重新规划新的管理模式,还是可以透过企业改造来加以调整,只是要多花一点钱而已!

4、部门代号规划建档:

部门代号的编码是最简单的工作,但是也是最麻烦的工作,主要原因是:每一家企业的部门组织表都经常改变,增加(扩编)部门,减少(缩编)部门,部门归属调整重组,几乎每一个企业都必须面对部门组织经常变更的问题。

当公司调整部门组织时,一方面要能够建立新的组织表,同时还要确保每个部门先前发生的营收和费用不会消失,或是无法连贯,部门组织规划就必须要设计成为可以弹性组合的方式,随时可以把一个部门的上级部门修改为另一个部门,却不须要修改部门代号和名称。万一有一个部门必须要取消掉,只要输入该部门的失效日期就可以,从该部门失效的日期开始,任何新增的单据资料都不能选用该部门代码。在数据库中却不须要急着删除该部门的资料。

至于部门代码要如何编制,首先把部门区分属性并编定代码2码,例如:管理性质(MN)、营业性质(SA)、服务性质(SV)、财务性质(FN)、制造性质(MF)、品管性质(QC)、研发性质(RD)、生管性质(PC)、物控性质(MC)、采购性质(PR)、生技性质(TL)、人力资源性质(HR)、法务性质(LW)等,属性代码使用数字也可以。然后按照部门级数从0级、1级、2级、3级、4级到9级,使用1码应该足够。相同属性而且又同个级数的部门,可以用01、02、03、04、05、06、07到99加以编码,或从001、002、003、004、005、006、007到999加以编码,即,使用2或3码。若集团企业需要把公司代码加到部门代码上的话,就在最后的两码或三码拿来当做公司代码即可。

5、生产线代码规划建档:

生产线/工作中心(Work center)和部门组织具有完全不同的属性,生产线/工作中心是指具备生产机能的单位,部门组织则是指在企业经营管理组织中行政运作的机能单位。

生产线/工作中心的规划编码,必须以生产管制部门的角度来规划。若生管人员安排生管排程到每一个机台,则每一个机台就是一条生产线(工作中心)。若生管人员安排生管排程到同型的整个机群,而每一个机台要生产甚么产品(工令单)是由车间现场主管决定,则整个机群就是一条生产线(工作中心)。

一条生产线(工作中心)的产能依据可能是以机器设备为主,或是以人工为主,或是以人/机同时配合为主。对于不同产业,生产线(工作中心)的产能依据都必须依据实际状况决定如何正确的加以规划。

生产线的代号最多可以使用8码,前2或3码为生产线的性质,后面的流水码则依据同型生产线的数量决定长度,可用1码、2码、3码、4码、或5码。例如:ZS01,ZS02,ZS03,表示成型注塑机01、02、03三条生产线。ZK01,ZK02,ZK03,ZK04,ZK05表示钻孔机01、02、03、04、05五条生产线。

6、仓库类别代码规划建档:

仓库的分类规划非常重要,因为仓库是存放存货的地方,为了要提高存货周转率,提高空间利用率,降低存货报废率,降低存货的存置成本,达到先进先出目标,同时还要能够符合政府合同核销海关保税帐务的相关法令规定。

仓库类别主要可以分为:一般存货仓、IQC进料检验仓、FQC完工待验仓、海关保税仓、车间线边仓、客户寄售仓、代送货仓、营销发货仓、海外发货仓、售服维修仓、厂商寄库仓、储槽存货仓、研发备品仓、冷冻仓、冷藏仓、AS/RS自动立体仓库、报废品仓等。若有其它类别的仓库,可以依据产业别的需求来定义。

除非有必要,通常不建议把仓库依据:成品仓、半成品仓、原材料仓、物料仓、商品仓、维修零组件仓来分类。因为各项料品的存量会不断增减变化,有可能原来存放制成品的仓库也把原材料存放进去,也可能原来存放原材料的仓库改存放半成品进去。

7、仓库/储位规划建档:

在存货管理的技术方面,我们建议采用十分钟存货管理法,可以在十分钟之内培训出非常优秀的仓库管理人才,这个管理技术将会在仓储存货管理分工体系中更详细加以解说。首先在这里必须强调几个观念:仓库和厂别/营所别不一定有绝对性的关系,因为,一个仓库的存货可以同时供给两个工厂或以上的用料,或是供应多个营业所的出货。

在仓库代码的规划方面,必须依据企业规模的大小和仓库的多少,来决定使用2码或3码做为每一个仓库的代码。

确定了仓库的编码之后,储位的编码就简单了,只要对于每一个仓库加以分区,再分段,再分层即可。至于每一个仓库的储位应该规划多大或多小的空间,必须依据产业类别的料品材积和存货数量而决定。

对于大型集团企业而言,不同的法人公司,除非会造成混淆,或有共用仓库的情况,否则可以使用相同的仓库代码,不会影响系统整合的问题。

8、员工代号规划建档:

员工代码的编码规则,最简单有效的方式为:前2码为员工到职的年度,后3码或4码流水码则为当年度员工到职的先后顺序。采用这种编码技术,员工代码可以永远不需要更改,直到退休或离职。因为从00年到99年的期间,没有任何一个员工会工作超过100年,而一个企业法人在同一年期间也不至于新进9999个员工,万一真的会超过9999人,就把流水号再加长到5码,可以让一年新进99999个员工。

集团企业如果有必要区分员工上班的公司别的话,可以在员工编码前面加上公司代码,2码或3码。

对于大型集团企业的员工代码规划方面,不同的子公司法人可以有各别的员工编码,不须要由集团总公司来统一编码。只要对于某一个层级以上的员工,或特殊才能的员工,才有必要将其个人资料转到集团总公司的人力资源运筹管理系统之中,也才需要另外建立一个集团总公司的员工统一编码,以完整记录该员工的所有信息。即,对于重要员工,除了其在服务的公司有一个员工代码之外,在集团总公司的人力资源运筹管理系统中,还有另外一个彙总统一编码。

9、经办人代号规划建档:

经办人代号和员工代号是相同的规则,所谓:“经办人”是指公司里边的间接员工,除了直接员工以外的人员。只要在人力资源管理体系中的员工基本资料建档作业中的“成本别”栏位输入“直接人工”以外的选项,都应该是间接员工,也都是经办人。

10、币别代号规划建档:

对于有和外国企业做交易的公司,使用外国币是必然的事情。对于各国币别代号的规划,只要使用国际货币标准代码就可以,不需要自己公司另外编码。例如:美金为:USD,人民币为:RMB,港币为:HKD。

11、每日汇率规划建档:

每日汇率是对于外国币别每天的汇率变动数据输入建档到电算化系统中,供各部门人员做为参考和工作执行的依据。尽管现今国家政策是采取人民币和美金是固定的汇率,但是对日币、港币、欧元、加拿大币等仍然是浮动汇率。何况一个强大的经济实体国家迟早必然会走向浮动汇率的政策方向,以大中国地区的经济发展速度来做分析预估,采取浮动汇率的货币政策应该是在未来5年之内的国家大事。

每日汇率是以本国币为基准,相对于外国币别如何转换。因为每一家银行订定买入/卖出的汇率可以不一样,所以每日汇率就必须分成5种汇率:银行买入汇率、银行卖出汇率、海关买入汇率、海关卖出汇率、中间汇率(平均汇率)。

营业部门在对客户报价、接订单、收款结汇等作业项目,应该使用银行买入汇率,其中收款结汇时使用的汇率是银行水单上面註明的汇率。在船务部门出货结关时所使用的汇率则要以海关买入汇率为准。而采购部门的请购单、采购单等作业项目,应该使用银行卖出汇率,采购验收单的汇率则必须配合到海关报关时INVOICE和报关单上面的海关核定汇率。国外采购使用外币的付款结汇作业,不论采用T/T或L/C或其它付款方式,则是以银行实际结汇的汇率为基准。

12、产制型态规划建档:

产品生产制造的型态可以区分为:离散型(Assembly type)和连续型(Routing type)生产型态。同一个产业里的产品生产过程,有可能部份部件(半成品或制成品)是属于离散型生产型态,而另外部份的部件则是属于连续型生产型态。在生管排程和生产制造的管理技术中,对于离散型生产型态的部件是以制造指令(工令单WORK ORDER)来做排程和生产进度的控管依据,而对于连续型生产型态的部件则是以途程单/流程卡(RUN CARD)做为排程和生产进度控管的依据。

13、产品分类规划建档:

一个制造产业所生产的产品,应该可以区分为许多产品类别,为了做为经营管理/分析的依据,就必须对各种产品类别加以编定代码,做为计算机统计数据的依据。

不同的产业型态对于产品的分类方式也不同,例如家电产业,其产品类别可能有:冷气机类、电冰箱类、微波炉类、电视机类、电风扇类等。PCB印刷电路板产业,其产品类别可能有:单面板、双层板、四层板、六层板、八层板、十二层板等。对于纺织产业,其产品类别可能有:平织部、针织部、提花布、不织部、毛绒布等。每一个产业都会依据本身经营管理的需要订定产品的分类。只是,不能把产品分类和产品型号混为一谈,所谓产品型号(Model)是指相同类别的产品,因为市场的需求和研发设计的不同,而有不同的款式或型号。例如:Motorola 388,它的产品分类是:“手机类”,产品型号则是:“388系列”。

14、料品科目规划建档:

料品科目是指:所有产业内部使用到的各项物品如何对应到会计总帐的会计科目,以便在各部门的相关单据输入计算机软件系统之后,可以自动产生会计凭证的会计分录。

料品科目可以分为:原材料(M)、半成品(S)、制成品(P)、商品(Z)、间接物料(低值易耗品)(U)、固定资产类(A)、费用类(F)、维修零组件类(T)、免费料品(N)、客户提供料品(O)、无库存货品等(W)。分别说明如下:

原材料(M):制造产业向供料厂商采购进料,做为产品生产过程中投入之直接原材料或间接原材料。

半成品(S):原材料经过生产制造程序,并移交仓库保存,但尚未完成制成品的阶段之货品。Semi product半成品,但不是在制品(Work in process)。

制成品(P):原材料或半成品经过最后完工程序,并移交仓库保存,等待出货的最终产品。

商品(Z):从供货厂商的公司进货之后,不需要经过生产制造的过程,就可以直接出货的货品。

间接物料(低值易耗品U):价格低廉,而且在产品的生产过程中不能核算入原材料的料品,例如打包带、去渍油、手套、橡皮筋等料品。

固定资产类(A):在会计总帐中列入固定资产的物品,例如:土地、厂房建物、机器设备、运输设备、通讯设备、办公设备、模具设备等项目。

费用类(F):在会计总帐中列入费用类的物品,例如:文具用品、办公用品、书报杂誌、杂项购置等物品。

维修零组件类(T):用于公司内部机器设备维修、保养的零件或组配件。

免费料品(N):不需要花钱采购,就能取得的料品,或是相对成本金额可以忽略的料品,例如:水、空气等。化工产业、饮料产业、医药产业等,使用大量的自来水或空气,就可以制造出产品出来,因为水的成本价格可以忽略,但是在生产投料时却要记录投入的数量或重量,才可以算出每一批产品的收率,这些料品直接视为免费料品,即,不必花钱,也不必办入库,却可以领用的物品。

客户提供料品(O):或称为:“客供品”,就是由客户提供给公司的料品。这类的料品虽然不需要公司花钱购买,却必需每天记录客户进料数量、领用数量、出货数量、和结余数量,并且要每个月和客户对帐,免得有一天客户说:“你们公司积欠我们公司一千五百万元的原材料”,这是我们过去辅导某家企业推行全面电算化之时所遭遇过的事件。

无库存货品等(W):有些产业的货品比较特殊,没有库存却可以不断的出货,例如:Microsoft 微软公司,他们只要授权给经销商,经销商就可以不必进货,而不断的出货,只要把版权费按时交给微软公司即可。客户也可以从网路上支付货款,然后直接下载软件或资讯,所以,软件产业的产品就是属于无库存货品,除非要录制成光碟才能出售者,则另当别论。

15、料品类别标准特性规划建档:

料品类别是要将制造产业所有的料品依据其功能属性加以分类,以利于工作分派,以及统计分析和管理。例如:电阻类、电容类、电线类、IC类、PCB类、外壳类、开关类、按键类、铭版类、螺丝类、化学药品类、包装箱类、标签类、塑胶袋类、说明书类等。

除了把料品分类规划建立之外,同时对于不同的料品类别具备的相关属性,也应该加以分析整理并建档起来。一个产业使用的料品种类可能有数十/数百/数千种大类,如果要透过各种料品的相关属性来统计/分析/查询所需要的资料,就必须把不同类别的料品具备的各项属性规划建立起来。例如:钢管类的料品,其属性有:长度、外径、内径、材质等。

16、料品品管类别规划建档:

制造产业对于每一项料品的质量检验方式,都有一定规范的品检方式和允收标准,将使用相同品检抽验方式、检验标准和允收标准的项目赋于一个代码,就称为料品品管类别。同一种品管类别可以应用于数种不同的料品分类项目,例如:电阻类和电容类的料品都使用相同品检抽验方式、检验标准和允收标准,也就是使用相同的品管类别。

17、料品质量等级规划建档:

料品质量等级规划是用来区别存货的质量等级,例如:良品、不良品、待检验品、待返工(重工)品、待报废品、报废品、次级品等。而不同的产业类别对于质量等级的规划也不相同,像瓷砖产业对产品的分级就有:检一、检二、检三、检四、检五等等级数,表示产品经过高温烧炉之后,其色泽的差异程度。有些产业对于存货良品再区分为:A级品、B级品、C级品,而其差异不一定表示品质的优劣程度,而可能是表示其尺寸的区间范围,例如轴承(Bearing)产业,其外环和内环必须以A级品、B级品、C级品的尺寸各自配套,才能配合安装钢珠后,制造出产品来。若以A级品的外环搭配B级品的内环,因为尺寸不合,就无法做出产品来。

库存料品的质量等级会影响MRP2数据的控管和运算结果,库存良品在MRP2的运算法则中是属于“供给量”,但是库存的不良品和报废品在MRP2的运算法则中则是属于“非供给量”。因为不良品对于MRP2的运算是没有办法确保正确性的一项数据。

18、料品特性对照表规划建档:

对于每一项料品特性的内容,有些特性具备固定的选项范围,可以事先规划建档,等到新增的料品建档时,就可以直接选择已经建档的资料,不容易发生错误。例如:电阻的阻值有固定的对照表,电阻的材质也有固定的对照表,纺织业使用的纱种也有固定的对照表,布匹染色的色号也有固定的色码对照表,制鞋业的鞋材也有其对照表。

19、料品特性项目规划建档:

对于产业中每一种料品的特性项目加以收集整理,并且建档处理。例如织布产业的料品特性有:纱种、染色色码、幅宽、印花花版、印花配色、克重(码重)、上浆、刷毛、亮光、颗粒、手感、剪毛、烧毛等。

20、质量检验项目规划建档:

对于各项料品的质量检验项目加以整理,并加以编码(包括原材料、半成品、制成品、商品等的检验项目),以便在建立料品检验规范的时候,可以直接选择质量检验项目代码,不需要重复输入许多资料。

21、不良原因代码规划建档:

对于产业内的所有原材料、半成品、制成品、商品等的质量不良原因项目加以整理,并加以编码,做为IQC、IPQC、PQC、FQC、QA和生产制造等发生质量不良的统计分析的依据。

22、区域代码规划建档:

依据企业的不同管理需求,对于客户和供料厂商的公司所在地区加以规划,并且编订代码。可以用于出货车程的安排用途,也可以做为营业统计分析的依据,或厂商分布地区的统计依据。

区域代码的规划会因为产业别的不同而有不同的编码方式,对于100%外销的企业而言,可以用洲别来规划区域代码,有些企业则是以每一个省当做一个区域,有些企业则是以每一个市当做一个区域,有些企业则是以每一个乡镇当做一个区域,或是以华北、华中、华东、华南、大西北做为规划区域的依据。

23、国别代码规划建档:

对于和公司有交易往来的客户和厂商的所在国家加以编码,并用于客户和厂商资料建档作业中,做为营销和进料统计分析的依据。

24、营业项目代码规划建档:

对于和公司有交易往来的客户和厂商的所有营业项目加以整理并编码,并用于客户和厂商资料建档作业中,做为将来查询资料的依据。

25、交易条件代码规划建档:

对于营业和各类采购的交易条件加以整理并编码,做为将来营业部门和采购部门处理各种报价、询价、接单、出货、采购等交易作业的依据。例如:FOB、CIF、C&F等交易条件。

26、结帐方式代码规划建档:

对于营业和各类采购作业的结帐收/付款方式加以整理并编定代码,做为将来营业部门和采购部门处理各种报价、询价、接单、出货、采购等结帐收/付款作业的依据。例如:T/T AT SIGHT、T/T BEFORE ? DAYS、T/T AFTER ? DAYS、L/C AT SIGHT、L/C USENCE、D/A、D/P、O/A、月结?天、次月结?天、旬结?天、货到付现金等结帐方式。

27、进/出口报单代码规划建档:

配合海关进/出口的报关规定,不同原因的进口和出口作业,都要填制不同的报单种类,以兹识别。而且,不同的进/出口报单在合同核销管理办法里,会影响海关的合同核销帐务记录。进/出口报单的代码直接使用海关规定的代码即可。

28、进/出口费用代码规划建档:

在公司进口货品或出口货品之时,都会发生不同的费用项目,例如:拖柜费、仓租费、保险费、运费、融资利息、报关费等,因为进口发生的费用和出口发生的费用在会计总帐中是以不同的会计科目入帐,所以必须分别编订进/出口费用代码,供相关部门在各项作业中使用。

29、会计凭证摘要代码规划建档:

对于会计总帐的会计凭证(传票)和应收/应付凭单的登帐作业中会经常使用到的摘要/备注,全部加以编码建档,以便在做帐时直接选用摘要/备注代码,提高作业效率。

30、品检AQL105D抽检标准对照表建档:

每一个制造产业对于厂内生产制造的、和委外加工的:制成品、半成品,以及采购的各项料品都有质量检验的标准,质量部门把这些标准的数据整理好之外,还必须建立到电算化的软件系统里,让计算机能够自行判断:在IQC/IPQC/PQC/FQC/QA的各种情况下,每一项料品须要采用哪一种检验方式和检验水准。

品检的抽检标准并不仅仅有AQL105D 一种,每个产业都可以依据实际需求状况建立自己的品检抽检标准,包括非国际标准,而是公司自行订定的标准。

31、采购人员代码规划建档:

对于每一个产业,因为采购工作量的大小不同,采购作业电算化的程度也不同,所以,聘用的采购人数也一定不同,采购工作的分派方式也会不同。先不论采购人数有多少,最重要的问题是:采购工作如何分派,采购人员的代号怎么编码?

采购人员的代号编码最好像买车票的柜台一样,从01,02,03,04,05.....编定,因为采购人员会流动,不论谁离职,谁到职,只要规定哪一号柜台买哪几类种别的料品,即可。

采购工作最好是依据料品类别分派,当料品数量大幅度增加的时后,可能要增加采购柜台,工作要重新分派,透过料品类别分派工作,只要几分钟就可以搞定,如果一项一项料品分派,就像发扑克牌一样,如果公司有3万种采购件料品,搞三天三夜不睡觉也还搞不好。

有些公司用供应厂商的所在地区来分派采购工作,就合理性方面就有重大问题,如果一项料品有三个供应厂商,分别在深圳、湖南株洲、福建厦门,难道要由三个人同时负责采购,难道要求三个人都必须同时了解同类料品价格谈判的成本结构吗?而且,将来请购同样的料品时,请购单要交给哪一位采购员?还是让他们三个采购员自行分配工作?这是一种不明确化,也不高效化的管理制度规划,光是请购单重新分配工作就增加许多工作量,而且请购单不知该如何填制了,应该是一张请购单填一项料品,或一张请购单填一项料品?

32、生管人员代码规划建档:

对于每一个产业,因为生管排程工作量的大小不同,车间的机器设备数量不同,使用模具/工具/治具/夹具的状况也不同,生管作业电算化的程度也不同,所以,需要的生管人数也一定不同,生管工作的分派方式也会不同。先不论生管人数有多少,最重要的问题是:生管工作如何分派,生管人员的代号怎么编码?

生管人员的代码应该和采购人员代码的编码方式相同,从01,02,03,04,05.....编定。至于生管人员的工作分派,就建议以机器设备(生产线/工作中心)的生产型态来规划安排。

33、物控人员代码规划建档:

物控人员的工作主要是负责监控制造产业的原材料和中间半成品的备料状况,让原材料和半成品的进料时间不会太晚(造成停工待料),也不会进料太早(造成存货积压/资金积压)。

物控人员的代码应该和采购人员代码的编码方式也相同,从01,02,03,04,05.....编定。至于物控人员的工作分派,则建议以料品类别来分派,每一个物控人员负责几种料品类别的管控。至于需要多少物控人员,则会因为选用ERP厂牌的好坏而有重大影响。如果ERP的物控功能很差,或没有功能,则,300人的小工厂,请30个物控人员也做不好物控工作。因为物控工作是不可能用人海战术来解决的。

34、仓管人员代码规划建档:

仓库管理对于任何企业都是非常重要的环节,许多公司的董事长或高阶主管可能都忽略了仓库管理的重要性。事实上,对于大多数的企业而言,库存品的合计总价值,可能比公司的银行存款多上十倍以上。如果忽略仓库管理的重要性,可能会比忽略银行存款的管理产生更严重的后果。

因为库存数量和帐务不符,比银行存款帐目不符更难查,但金额可能更大。若库存管理不善而产生报废,就等于手上的现金钞票被白蚂蚁吃掉,只是很奇怪:大部份的人看到钞票被白蚂蚁吃掉会心痛,但是存货拿去报废好像心理比较能够接受!

仓库人员代码的编定,应该和采购人员代码的编码方式也相同,从01,02,03,04,05.....编定。至于仓管人员的工作分派,则建议以仓库别来分派,即:每一个仓库由谁控管,包括帐和物品都要由他负责,如果没有固定负责人员,就表示谁都要负责,也等于谁都不必负责。

仓库的搬运人员和仓管人员不同,仓管人员必须对物/帐负责,搬运人员只要配合仓管人员指示把存货存放在定点,或从指定的储位领取物品,并运交到指定的部门和地点即可。一个(或几个)仓库只可以有一个仓管人员(仓管柜台),但同时可以有数名搬运人员。

35、原始凭证代码规划建档:

所谓的原始凭证,指一个产业(企业)所使用到的各种单据。单据和报表不同,单据是表示在各种作业过程中,部门和部门之间,个人和个人之间,责任的转移、物品的转移、金钱的转移、帐务的转移、或任务的下达,所依据的书面格式,经手承办的人都必须签名盖章,表示负责。也做为将来在公司内部规章或在法律上责任判定的依据。

报表则是从某一种(或某几种)原始凭证的数据资料中整理出所需要的信息,再依据使用的必要性来决定需不需要签名盖章。就算在报表上签名盖章,万一发现数据资料不符,也只能算是疏忽,真正的问题还是来自原始凭证的错误,或报表输出软件的错误。例如:某月份的损益表数据不对,肯定不是签名盖章的时候发生错误,若不是会计凭证登录错误,就是计算机软件错误。若是会计凭证登录时发生错误,就表示当时会计凭证制单/签核盖章的人要负责,不论用人或计算机整理报表是取用会计凭证的数据资料,要如何负责?这就是单据(原始凭证)和报表的差异。

每一个产业对于公司所有使用到的内部凭证/对外凭证/外来凭证都要全部加以整理/编码,并且规划改善。尽管是推行ISO质量认证体系,或推行股票上市的内部控制/内部稽核体系,也都必须要把所有的原始凭证重新整理一次。何况是推行ERP全面电算化的经营管理整合信息系统,只要不能符合:明确化/合理化/规范化三种条件,就注定全面电算化保证失败,除非系统不做整合(不整合的电算化系统就是会产生许许多多信息孤岛)。何况一个企业达到:明确化/合理化/规范化的程度,并不表示已经达到高效化、精细化、自动化的程度。

推行ERP全面电算化的经营管理整合信息系统,所有原始凭证都必须经过重新规划审察过。既然称为信息整合管理系统,就表示每一张原始凭证在规划设计时都必须考虑具备(1)和四大流量相互整合的数据接口(物流/帐流/资金流/信息流),(2)和各个循环/分工体系之间的接口,否则如何称得上是全面电算化整合信息管理系统呢?

一个产业的每一张单据就像是人体组织的每一个器官一样重要,举例说明:人体的嘴巴器官,会连结到:呼吸循环、血液循环、淋巴循环、消化循环,同时也连接到:肌肉组织、神经组织、骨骼组织、皮肤组织等。经营管理的客户订单,会连结到:财务资金循环、生产制造循环、产品研发循环、存货管理循环、委外加工循环,同时也连接到:制程工程(工业工程)分工、生产管制分工、物料控制分工、制造成本分工等体系。

人体复杂而精细结构的规划设计是靠宇宙的造物者的创意,产业全面电算化的经营管理整合信息系统的规划设计则是靠专业的架构规划师(ERP Architecture)来创造。如何让制造产业的ERP全面电算化的经营管理整合信息系统能够规划设计到有如人体的组织结构一样灵活精细,就是产业能否真正具备十六大竞争优势的决战关键。

本人以财务资金循环体系和营业收款循环体系的一部分功能做为范例,来提出它们之间会牵涉到的系统整合的相关技术,如果您有办法提出完整解答,才表示您真正具备了系统评鉴的能力。(例题):营业部门的出货作业:(a)、营业部门的出货作业同时会应用到哪些相关单据?包括:内销作业、外销作业、合作外销、转口贸易。(b)、营业部门的出货作业会和财务资金循环体系有哪些关联?何谓六大帐册?和营业收款体系之间有何关联?(c)、营业部门的出货作业会在甚么时机才真正进入财务循环立帐?又如何确保所立的帐是100%正确?还能够做到双向稽核?不担心漏帐/错帐/重复登帐?(d)、财务循环体系必须每个月结帐,提出相关财务报表,对于交易程序尚未完成的部份,该如何配合处理?

上面四个问题的相关系统整合技术将留在营业收款循环体系章节中详细解说,以确保内容的完整性和连续性。

以上是指以财务/会计为核心的最关键性的系统整合技术(营业收款循环体系和财务资金循环体系能够整合,就表示其它循环体系和财务资金循环体系也应该能够整合,整合技术是相类似),也是身为一个现代化高阶经营管理者及信息化部门主管必备的专业知识。少了这一项专业认识,企业的竞争风险就增加几分。如果同业在这个领域有所突破,就表示这个同业已经进入高度财务管理自动化的运作模式,而且已经可以做到:防弊、防错、防呆、防人员流动、防信息流失、防知识断层的经营管理水平。

36、银行(金融机构)代码规划建档:

银行(金融机构)就是指所有国内外以钱为主要商品,或是有专业从事资金流通/融通借贷/投资/转帐/债券发行业务等的企业法人,包括银行、合库、农会、信托局、邮局、债券公司等等。

对于国内的银行(金融机构),凡是和公司有往来的银行肯定要编码建档,接单客户和往来厂商跟我们公司有关系的银行也要编码建档。而银行(金融机构)的编码规则,直接采用中央银行编订的标准代码就可以了,不需要另行编码。

37、存款帐号代码规划建档:

存款帐号主要就是指公司在银行(金融机构)开立的各种类型的存款帐户,包括:活期存款、支票存款、定期存款、融资偿债专户、投资专户等等。而且,同性质的存款帐号还有各种不同币别的帐户,例如:人民币帐户、美金帐户、港币帐户、日币帐户等等。

对于存款帐户的编码技术,建议采用下列原则:存款种类用一码,币别用二码,流水号用两码或三码。理论上银行存款属于相同种类性质,又相同币别,能够用到999个帐号,这个国际集团企业也确实是具备相当的规模了,但也不至于用到999个帐户吧。

银行存款帐户规划编码好了,就可以自动生成银行存款的会计科目,即:银行存款的统制科目(4码)+款帐户的编码(5至6码),就等于会计总帐管理系统的银行存款明细科目。将来所有银行存款帐户的资金存/取变动记录,就可以从银行存款帐和会计总帐自动产生整合互动。不需要人工重复登帐了。

38、存款异动摘要代码规划建档:

每一个银行存款帐户的每一笔存/取/变动(异动),都会有其原因,为了将来能够清楚瞭解并追查银行存款帐户的变动,就必须把每一种变动原因加以编码。并且,把存款增加的原因代码的第一码用“D”,表示Debit(借方);存款减少的原因代码的第一码用“C”,表示Credit(贷方)。

39、年度周别规划建档:

一年有52周虽然是常识,但是在系统整合的信息上,还是要明确表示在系统上,并且包括近期两年的数据资料,以便在生产管制和物料控制作业上运用,另外在中长期资金调度预估表上,也是以周别的方式来表达资金状况是否足够。

40、银行行事历资料建档:

银行的行事历和公司的行事历并不相同,因此必须另外建档。银行的行事历最主要是会影响应收/应付票据的票面到期日和托收银行的实际兑现日的银行存款立帐作业。

41、公司行事历资料建档:

对于公司每个月的行事历,人事部门都必须要在每个年度到来之前规划建档,以便其它部门的各项计划作业能够顺利进行。

42、利润中心(专案)代码规划建档:

如果产业推行利润中心、成本中心、专案管理的话,就必须在每一个利润中心、成本中心、专案管理项目成立时,把其代码和名称等数据资料规划建档,以便其它部门可以取用。

如果利润中心、成本中心是以:部门、厂别、营所、事业处(部)、产品类别为核算基础的话,就不须要在本作业画面另外建档,这些资料已经在其它作业项目建档了。而且,透过会计总帐的会计科目立冲要件设定,就能自动产生上列部门别损益表、厂别损益表、营所别损益表、事业处(部)别损益表、产品类别损益表等。

所谓专案管理项目,主要是针对:工程承包合约、工程发包合约、新厂房建厂专案、新产品开发专案、或是一些项目型接案的产业等,就必须能够应用专案管理的功能。

43、票据类别代码规划建档:

对于公司在财务运作过程中会使用到应收/应付票据的票据种类加以分类/编码/建档。例如:支票、本票、汇票等。

44、会计凭证(传票)种类代码规划建档:

会计传票一般分为:(1)现金收入传票 (2)现金支出传票 (3)收入传票 (4)支出传票 (5)转帐传票等五种,如果万一又有新的分类产生,就可以再自行增加。

45、往来对象类别代码规划建档:

往来对象类别代码是将公司往来的客户、供料厂商、委外厂商、往来银行(金融机构)、政府机关、学校、母子公司、关系企业等,依据产业的管理需要,及不同属性的往来对象特性,编定不同的往来对象类别代码,供往后做管理分析使用。例如:对于往来客户来说:有些公司是以:开发中客户(K)、交易中客户(J)、停止交易客户(T)、拒绝往来客户(G)。而往来厂商的分类则可以另外依实际需要来规划编码处理。

往来对象的“类别”和“等级”的概念不同,等级是指:A级、B级、C级、D级、E级、或01级、02级、03级、04级、05级、06级等。

46、呆滞料品原因代码规划建档:

为了对于产业中产生呆滞料的原因加以编码区分,以便确认部门和个人的权责,并且能够对每周/每月/每季/每年做统计分析,让每个部门和个人会随时加以警惕,可以大幅度降低呆滞料品产生的成本损失。

一个产业的经营过程中,可能造成呆滞料品的部门和原因很多,例如:产品研发设计不良、业务订单产品打错、业务订单数量打错、客户订单变更、物控核料项目错误、物控核料数量错误、采购部门买错料、采购部门多买料、生管工令单开错产品、生管工令单开错数量、仓管发错料、仓管搬运摔毁、制造部门用错料、制造部门超产、交期延误遭客户取消订单等。项目和权责规划越清楚明确,就越能降低呆滞料品的损失。

47、料品材质代码规划建档:

如果产业对于使用料品的材质很重视,则必须把各种使用到的原材料材质加以分类规划编码,做为产业经营管理分析的依据。例如:鞋业、成衣业、皮件业、包袋业等。

48、营业税申报地点代码规划建档:

营业税/增值税等是属于地方税,一个公司法人可能跨好几个地区经营,包括各个分厂、营业所、办事处,所以对于公司所有的营业税/增值税等申报地点必须先行整理编码建档,做为各个分厂、营业所、办事处资料建档时,及发票处理作业时,可以顺利应用。

49、备注说明代码规划建档:

产业全面电算化整合信息系统建立实施之时,有许多电算化作业会重复应用到相同的词句、备注、摘要等,为了避免重复输入,浪费人工时间,可以事先将这些词句整理编码建档,供相关作业中选用。

在编定词句、备注、摘要等代码时,最好要依据用途/性质分类,再编码,免得资料多了之后会找不着。

50、料品单位代码规划建档:

对于公司的全部料品使用到的单位,若有统一的必要,可以先在全面电算化实施的前期加以规化建立,这样可以避免相同料品分类的东西,却用不同的单位表示,例如:同样是电阻类的料品,有些用个,有些用颗,有些用粒,有些用PCS,有些用PS,在数据计算上是没有甚么影响,但是就是列印报表时会出现许多不同的单位符号,看起来不统一。

51、往来客户代码规划建档:

对于公司往来的客户资料,全部加以编码建档。客户编码采用的编码规则建议如下:(a)、对于国内使用中文的公司,直接以公司名称的前四个中文字的罗马拼音的第一段编码,4码以后则用流水码,可避免前4码重复。至于流水码要用几码,要看往来客户和厂商的家数多少来决定,最多可以用到4个流水码。至于前四码如何编订,最好是所在县市地区放在前二码,公司名称放在三四码,例如:宁波顺发金属有限公司,其代码为:NBSF001。宁波升华工业股份有限公司,其代码为:NBSF002。宁波申富泉实业股份有限公司,其代码为:NBSF003。虽然罗马拼音相同,但是流水码并不相同,使用者马上可以用前四码查询到这三家客户的资料。(b)、对于国外非使用中文名称的公司,则直接使用其英文名称的前四码,再依据外销客户数量多少决定加上几码流水码,将来就可以简单的进行查询的作业。

52、往来厂商代码规划建档:

对于公司往来的厂商资料,全部加以编码建档。往来厂商编码采用的编码规则建议和往来客户采用相同的规则,不需要另外再订定编码规则。

尤其,有些客户也可能是厂商身份,到底要分别用一个代码,或共用一个代码?如果每个月结帐时,该客户同时有应收帐款,也有应付帐款发生时,如何让应收帐款和应付帐款能够对冲?

如果使用两个往来对象的方式,应收帐款和应付帐款是不能够对冲的,如果开放不同厂商客户间可以应收帐款和应付帐款能够对冲,则将来财务管理系统大乱的机会将大增,而且,人为的疏忽或作弊的可能性就会增加,当几百家/几千家客户和厂商的应收帐款和应付帐款大乱之后再来整帐,大部份的财务人员会投降,因为应收帐款和应付帐款大乱,就表示会计总帐肯定也出大问题。所以,不同往来对象的账是不能相互对冲的。而相同的一个往来对象同时具备客户和厂商资格时,最好的办法就是只用一个往来对象代码。

53、公司股东资料规划建档:

公司的股东有可能是自然人股东,也可能是法人股东。由于公司的股东必定和公司会有某些必然的往来事项,所以就必须加以编码建档。一般股东的资料保存期限都很长,所以所有股东的资料都不能轻易删除,也就必须在股东编码时把码数加大,免得将来不够使用。尤其,没有人可以预知公司的发展会到甚么规模?也就无法预测公司的股东人数会有多少。例如:一个200人的企业,有可能发展到20,000人,而成为一个上市公司,然后再发展到国际性集团企业,其股东人数可能从原来的独资个人,变为数十万个股东的国际性集团企业。经过了十年二十年之后,股东的持股转换,就可以达到数百万/数千万个股东资料的情况。

54、其它往来对象代码规划建档:

所谓其它往来对象的范围,就是母子公司、关系企业、往来客户、往来厂商、公司股东以外的政府机关、学校、慈善机构等等,会和公司在非交易性质的事务上往来的各种对象。其编码方式和客户/厂商相同,在查询资料上会比较简单。

55、使用者权限规划设定:

对于公司全面电算化的软件系统使用上有被授权者,都必须设定其使用者权限,做为对其工作范围和权责大小的规范,同时也对产业的机密加以更严格的控管。

对于使用者权限的控管,可以控管到:系统模块、作业项目、每项作业的新增/修改/删除/查询/审核/作废/确认/反确认/列表等,以及重要栏位(字段)的锁定。一旦使用者权限设定完成,每一个使用者就只能看到自己被授权的功能范围,以降低系统使用的复杂度。

56、年度会计周期规划设定:

每一个企业都可以有自己的会计周期规划,对于不同的国家,使用的会计周期更是多样化。有些公司是以每年的一月到十二月为年度会计周期,有些公司是今年的五月到明年的四月为年度会计周期,有些公司则是以周别区间来结算各月份的损益和资产负债等财务报表,每年的一月是以第一周来起算,而不是元月一日起算。

面对各国的各种会计周期差异,就必须提供会计周期设定的功能。而且,当面对一个跨国的集团企业,财务总监如何处理不同国家的会计周期,并且还要能够达成集团企业全球会计合并彙总的目的,就是一个重要关键性技术。事实上,只要在全面电算化整合性管理信息系统中同时提供两个会计周期设定的功能即可以解决这个严重的问题。

安全与便捷,本质上是用户体验与风险控制之间的动态平衡,但是在电子签章的实际应用中却给用户完全不同的操作体验。那我们应该如何去把控呢?

  1. 核心矛盾与解决框架

Ø 便捷性追求:快速、远程、无纸化、低成本、易操作、跨平台。(典型代表:法大大、上上签、E签宝等电子签章公司)

Ø 安全性追求:身份真实、意愿真实、文档防篡改、过程可追溯、法律效力强。(典型代表:安证通、点聚、契约锁等电子签章公司)

Ø 平衡框架:“分场景、分等级、强技术、简操作”。不是所有签署都需要银行级安全,也不是所有文件都可以一个短信了事。

  1. 实现平衡的关键技术手段(安全基石)

这些技术在不增加用户感知复杂度的情况下,提供了强大的底层安全保障:

Ø 数字证书与PKI体系:这是安全的核心。由权威CA机构颁发的数字证书,能唯一标识签署者身份,并实现数字签名和加密。用户无需理解其原理,只需完成一次实名认证。

Ø 可靠的电子签名:符合《中华人民共和国电子签名法》规定,能够识别签名人身份并表明认可内容。

Ø 哈希算法与时间戳:确保文档一旦签署,任何改动都能被侦测,并精确记录签署时间。

  1. 在用户体验层面的平衡策略(便捷体现)

1) 分级安全策略:

Ø 低风险场景(如内部审批、普通协议):可采用短信验证码+实名认证的方式,便捷性极高。

Ø 中风险场景(如采购合同、服务协议):推荐使用数字证书签名,结合人脸识别或指纹等生物特征进行意愿确认。

Ø 高风险场景(如金融借贷、重大交易):必须采用数字证书+强生物特征识别+过程录音录像,确保身份与意愿的双重强验证。

2) 流程优化:

Ø 模板化与批量签署:对于格式固定的文件,一次制作,多次使用。

Ø 移动化与云端协同:随时随地通过手机、平板签署,无需专用设备。

Ø 与业务系统集成:将签章能力嵌入OA、CRM、ERP等系统,实现一键发起、无缝流转。

3) 透明的验证机制:

Ø 提供便捷的验签功能,任何接收方都能轻松验证签名的有效性和文档完整性,这本身就是一种安全信任的建立,也提升了协作效率。

  1. 平衡点的具体体现(理想状态)

一个优秀的电子签章服务,其平衡点体现在用户侧和治理侧:

1) 对签署方:

Ø 第一次使用:可能需要完成一次稍复杂的实名认证(如上传身份证、人脸识别)。这是为后续所有便捷性支付的“安全成本”。

Ø 后续每次签署:流程极其简单(如点击链接→查看文件→输入短信验证码/刷脸→完成),但背后安全机制(数字签名、哈希、时间戳)全自动运行。

2) 对企业管理者/法务:

Ø 可配置:能为不同合同类型设置不同的安全等级。

Ø 可审计:所有签署过程全链路存证,生成完整的证据报告,随时可查、可溯源。

Ø 合法合规:严格遵循法律法规,确保电子文件在法律纠纷中可作为有效证据

根据目前市场各个电子签章公司发布的产品以及实际客户应用场景来看,操作安全性与操作便捷性平衡点把控的比较好的签章公司如下:

Ø 第一梯队:北京安证通、腾讯电子签、可信签;

Ø 第二梯队:E签宝、契约锁;

Ø 其他:法大大、上上签等。

一个多月前,下楼吃饭时看见门口停着辆警车,有两个警察正下车往物业办公室跑。

吃完东西回来正好看到小区群里有人发了条消息:

“以后你们在车库充电瓶车,插头被拔了直接报警就行”。

出于好奇,我问了一句:

“刚才看到小区里有两个警察,就是因为这个事?”

这个人就开始滔滔不绝的回复。

大概就是有人在车库公共充电桩(扫码付费供电那种)给自己的电瓶车充电,但是被人拔了,导致第二天上班时发现没电了,只能打车去上班,结果堵车导致迟到,被扣了半天工资和当月绩效,气不过就报警了,主张拔插头的人赔偿被扣的半天工资 300 元。

自此画风都还算正常,直到这位大姐画风一转:

“赔 300 ?根本不可能,我最多只赔他 50”

我一脸懵逼,合着是你就是当事人,你拔了别人插头?

她:“对呀,那咋了,就这几个插座,我不拔怎么充电?”

我当时就感到氛围不对,就没有回复了。

结果这位姐还一直在群里滔滔不绝的说,大概就是觉得受害者小题大做,这点事至于报警嘛,至于索赔嘛。

最绝的是,群里居然几乎所有说话的人都是帮腔的,均认为是受害者有罪。

后面甚至演变为人身攻击和阴阳怪气的:

“半天工资 300 元?工资这么高还骑电瓶车?”

“堂堂男子汉还这么小气”

“让派出所以后在我们小区设个警务站得了”

“就这么几个插头,不拔你的回来晚了怎么充电,晚来的不配充电?”

偶尔有几个人质疑拔别人正在充电的插头真的好吗?

也会被反对声淹没。


然后,搞笑的来了。

这段时间开始陆续有人在群里咆哮:

“谁拔了我的插头!害我上班迟到了!”

一开始群里的回复都是:

“那你报警啊”

后来被拔的人越来越多,画风又变了。

开始变成一致谴责乱拔别人插头的了。

我搜了下聊天记录,其中不乏之前“网爆”报警人的住户。

用户身份认证是网络安全的重要组成部分,对用户登录尝试行为的审计,是识别可疑操作的关键环节。

登录失败通常由以下两种情况引发:

用户提供的身份凭证无效
用户不具备访问特定资源的登录权限
当用户通过 SSH 远程连接系统,或使用 su 命令切换用户身份时产生的登录失败事件,属于需要重点监控的内容。这类事件可能预示着有人正在尝试非法入侵系统。

本文将详细介绍查看 SSH 登录失败记录的具体方法。

查看 SSH 登录失败记录的操作步骤

可插拔认证模块(PAM)会记录此类身份认证事件,借助模块生成的日志,能够有效识别恶意登录行为与异常访问操作。

以下是一则登录失败的日志示例:

pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.0.2.2

        Failed password for invalid user robert from 10.0.2.2 port 4791 ssh2
        pam_unix(sshd:auth): check pass; user unknown
        PAM service(sshd) ignoring max retries; 6 > 3

为了高效排查问题,管理员需要快速定位所有此类关键登录事件,并采取对应的处置措施。

下文列出了查询所有 SSH 登录失败记录的操作步骤:

列出所有 SSH 登录失败记录的基础命令:

grep "Failed password" /var/log/auth.log

也可以通过 cat 命令实现相同效果:

cat /var/log/auth.log | grep "Failed password"

如需显示 SSH 登录失败的更多相关信息,可执行以下命令:

egrep "Failed|Failure" /var/log/auth.log

如需列出所有尝试登录 SSH 服务器但失败的客户端 IP 地址,可执行以下命令:

grep "Failed password" /var/log/auth.log | awk '{print $11}' | uniq -c | sort -nr

尽管分析上述事件的操作看似简单,但手动执行所有相关步骤耗时又费力。借助专业的日志管理解决方案,能够更便捷地分析 SSH 登录失败尝试行为。

uniappx服务端推送消息配置

一.前置条件

1.申请Dcloud 开发者账号(https://www.dcloud.io/
2.HBuilder安装
3.安装模拟器
4.uni-push 2.0 文档(https://uniapp.dcloud.net.cn/unipush-v2.html
5.创建一个uniappx项目
image.png

二.配置步骤

1.确认AppID

打开项目中 manifest.json 文件,确认AppId是否存在,若不存在则点击右侧 重新获取 按钮(此处可能需要登录Dcloud账号),会生成AppID
image.png

2.构建项目生成证书

点击 Hbuilder 菜单 运行 》 运行到手机或模拟器 》 制作自定义调试基座
image.png
点击打包,会出现打包校验提示,继续打包即可,随即会在控制台打印相关信息,此处等待时间可能较长,我们继续推进下一步,打包后台运行即可。
image.png

3.新建uniCloud

登录Dcloud 开发者中心,点击左侧uniCloud...
image.png
在新标签页中点击右上角新建服务空间,按提示完成即可,例子中建立一个叫uniapp-hello 的服务空间(取名仅作区分,无其他含义,视自己习惯命名即可);
image.png

4.创建应用信息推送

回到Dcloud开发者管理页面,点击左侧uni-push > 2.0(支持全段推送) > 应用信息
image.png
点击当前应用下拉框,选择我们需要推送的应用
image.png

选择平台视业务而定,此处示例仅勾选Android
image.png
点击选择Android包名,若包名不存在,则需等待上一步打包结束后刷新当前页面重新选择,
再添加云服务空间,选中上一步创建的空间即可,最后点击开通应用
image.png

5.创建云函数

在项目目录下的uniCloud 》coudfunctions 目录右键,选择新建云函数/云对象(若没有uniCloud目录可在项目根目录上右键,选择 创建uniCloud云开发环境 )
image.png
填写函数名点击创建即可
image.png
随后替换新建函数下的index.js 和 package.json 内容
image.png

index.js新内容如下(需替换第二行中自己的appId):


'use strict';
const uniPush = uniCloud.getPushManager({appId:"__UNI__XXXXX"}) 
exports.main = async (event, context) => {
    const body = JSON.parse(event.body);
    return await uniPush.sendMessage({
        "push_clientid": body.cid,     
        "title": body.title,    
        "content": body.content,
        "payload": body.data
    })
};
 

package.json新内容如下:

{
    "name": "photo_push",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "extensions": {
        "uni-cloud-push": {} 
    },
    "author": ""
}

6.增加uni-push 能力

在Hbuilder中打开manifest.json,勾选uni-push(消息推送)
image.png
在新建立的photo-push 目录上右键,选择 管理公共模块或扩展库依赖
image.png
选中统一推送服务,点击确定
image.png

7.增加扩展库依赖表

在database目录下增加以下依赖表文件(文件内容见结尾附件)
image.png
在 opendb-device.index.json 右键 》 初始化云数据库索引
剩余其他三个文件 右键 》 上传DB schema

8.上传部署云函数

随后在photo-push 目录点击 右键 》 上传部署,等待上传完成即可
image.png

9.云函数URL化

回到第三步创建发unicloud服务空间,点击 服务空间 名称进入详情页
在左侧 云函数/对象列表找到创建的云函数
image.png
点击函数名进入详情页,页面底部 云函数URL化编辑配置函数名 /sendMessage
注:每个服务空间内函数名不可重复,且URL路径不可出现重复部分
image.png

10.项目增加消息监听

在项目App.uvue中 onLaunch()生命函数中增加监听代码
image.png

uni.onPushMessage(res => {
                console.log("监听消息:", res)                
                if (res.type == "click") {
                    console.log("点击消息:" + res)
                }
                if (res.type == "receive") {
                    console.log("收到APP消息" + res.data);
                    // 创建本地通知栏消息
                    uni.createPushMessage({
                        title: res.data.title as string,
                        content: res.data.content as string,
                        payload: res.data.payload
                    })
                }
            }) 

11.启动项目

启动模拟器,此处以 网易Mumu模拟器 演示
Hbuilder 菜单点击 运行 》 运行到手机或模拟器 》 运行到Android App 基座
选择设备后运行,等待控制台编译完成
image.png
控制台选择 连接云端云函数
image.png

12.发起调用

使用云函数URL发起调用
image.png

效果如图
image.png
请求参数说明:

{
    "cid": ["02e3c939927d45df1028b274e493488c"], // 设备ID,长度不超过500
    "title": "绿12",
    "content": "收到消息12",
    "data": {    // data 为自定义业务参数,该字段可不传
        "type": "messageList"
    }
}

附件

●opendb-device.index.json

[
    {
        "IndexName": "index_device_id",
        "MgoKeySchema": {
            "MgoIndexKeys": [
                {
                    "Name": "device_id",
                    "Direction": "1"
                }
            ],
            "MgoIsUnique": true
        }
    }
]

●opendb-device.schema.json

{
    "bsonType": "object",
    "required": [],
    "permission": {
        "read": false,
        "create": true,
        "update": false,
        "delete": false
    },
    "properties": {
        "_id": {
            "description": "ID,系统自动生成"
        },
        "appid": {
            "bsonType": "string",
            "description": "DCloud appid"
        },
        "device_id": {
            "bsonType": "string",
            "description": "设备唯一标识"
        },
        "vendor": {
            "bsonType": "string",
            "description": "设备厂商"
        },
        "push_clientid": {
            "bsonType": "string",
            "description": "推送设备客户端标识"
        },
        "imei": {
            "bsonType": "string",
            "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)"
        },
        "oaid": {
            "bsonType": "string",
            "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)"
        },
        "idfa": {
            "bsonType": "string",
            "description": "iOS平台配置应用使用广告标识(IDFA)"
        },
        "imsi": {
            "bsonType": "string",
            "description": "国际移动用户识别码(International Mobile Subscriber Identification Number)"
        },
        "model": {
            "bsonType": "string",
            "description": "设备型号"
        },
        "platform": {
            "bsonType": "string",
            "description": "平台类型"
        },
        "uni_platform": {
            "bsonType": "string",
            "description": "uni-app 运行平台,与条件编译平台相同。"
        },
        "os_name": {
            "bsonType": "string",
            "description": "ios|android|windows|mac|linux "
        },
        "os_version": {
            "bsonType": "string",
            "description": "操作系统版本号 "
        },
        "os_language": {
            "bsonType": "string",
            "description": "操作系统语言 "
        },
        "os_theme": {
            "bsonType": "string",
            "description": "操作系统主题 light|dark"
        },
        "pixel_ratio": {
            "bsonType": "string",
            "description": "设备像素比 "
        },
        "network_model": {
            "bsonType": "string",
            "description": "设备网络型号wifi\/3G\/4G\/"
        },
        "window_width": {
            "bsonType": "string",
            "description": "设备窗口宽度 "
        },
        "window_height": {
            "bsonType": "string",
            "description": "设备窗口高度"
        },
        "screen_width": {
            "bsonType": "string",
            "description": "设备屏幕宽度"
        },
        "screen_height": {
            "bsonType": "string",
            "description": "设备屏幕高度"
        },
        "rom_name": {
            "bsonType": "string",
            "description": "rom 名称"
        },
        "rom_version": {
            "bsonType": "string",
            "description": "rom 版本"
        },
        "location_latitude": {
            "bsonType": "double",
            "description": "纬度"
        },
        "location_longitude": {
            "bsonType": "double",
            "description": "经度"
        },
        "location_country": {
            "bsonType": "string",
            "description": "国家"
        },
        "location_province": {
            "bsonType": "string",
            "description": "省份"
        },
        "location_city": {
            "bsonType": "string",
            "description": "城市"
        },
        "create_date": {
            "bsonType": "timestamp",
            "description": "创建时间",
            "forceDefaultValue": {
                "$env": "now"
            }
        },
        "last_update_date": {
            "bsonType": "timestamp",
            "description": "最后一次修改时间",
            "forceDefaultValue": {
                "$env": "now"
            }
        }
    },
    "version": "0.0.1"
}

●opendb-tempdata.schema.json

{
    "bsonType": "object",
    "required": ["value", "expired"],
    "permission": {
        "read": false,
        "create": false,
        "update": false,
        "delete": false
    },
    "properties": {
        "_id": {
            "description": "ID,系统自动生成"
        },
        "value": {
            "description": "值"
        },
        "expired": {
            "description": "过期时间",
            "bsonType": "timestamp"
        }
    }
}

●uni-id-device.schema.json

{
    "bsonType": "object",
    "required": [
        "user_id"
    ],
    "properties": {
        "_id": {
            "description": "ID,系统自动生成"
        },
        "user_id": {
            "bsonType": "string",
            "description": "用户id,参考uni-id-users表"
        },
        "ua": {
            "bsonType": "string",
            "description": "userAgent"
        },
        "uuid": {
            "bsonType": "string",
            "description": "设备唯一标识(需要加密存储)"
        },
        "os_name": {
            "bsonType": "string",
            "description": "ios|android|windows|mac|linux "
        },
        "os_version": {
            "bsonType": "string",
            "description": "操作系统版本号 "
        },
        "os_language": {
            "bsonType": "string",
            "description": "操作系统语言 "
        },
        "os_theme": {
            "bsonType": "string",
            "description": "操作系统主题 light|dark"
        },
        "vendor": {
            "bsonType": "string",
            "description": "设备厂商"
        },
        "push_clientid": {
            "bsonType": "string",
            "description": "推送设备客户端标识"
        },
        "imei": {
            "bsonType": "string",
            "description": "国际移动设备识别码IMEI(International Mobile Equipment Identity)"
        },
        "oaid": {
            "bsonType": "string",
            "description": "移动智能设备标识公共服务平台提供的匿名设备标识符(OAID)"
        },
        "idfa": {
            "bsonType": "string",
            "description": "iOS平台配置应用使用广告标识(IDFA)"
        },
        "model": {
            "bsonType": "string",
            "description": "设备型号"
        },
        "platform": {
            "bsonType": "string",
            "description": "平台类型"
        },
        "create_date": {
            "bsonType": "timestamp",
            "description": "创建时间",
            "forceDefaultValue": {
                "$env": "now"
            }
        },
        "last_active_date": {
            "bsonType": "timestamp",
            "description": "最后登录时间"
        },
        "last_active_ip": {
            "bsonType": "string",
            "description": "最后登录IP"
        }
    },
    "version": "0.0.1"
}

一、背景与痛点:中小制造企业的“订单管控困局”

当前,中小制造/工贸企业普遍面临六大核心痛点:

  1. 订单全流程断裂:销售、生产、仓库、财务数据孤立,无法形成闭环;
  2. 非标定制低效:复杂参数配置难、流程适配性差,无法满足机械装备、定制家居等场景;
  3. 生产排程混乱:依赖人工经验,产能与订单交付不匹配,延期率高;
  4. 物料管理粗放:BOM拆解不精准、领料无追溯,导致物料浪费或停工待料;
  5. 财务联动薄弱:应收触发不及时、回款核销混乱,资金流风险高;
  6. 多端协同缺失:内部团队与客户无法实时同步订单进度,沟通成本高。

针对这些痛点,本文选取9个主流CRM/ERP品牌(覆盖中小制造、大型企业、销售驱动、跨国场景),从订单全流程管控、非标定制、生产排程、BOM领料、财务联动、多端同步六大维度展开深度对比,为企业选型提供参考。

二、核心概念与对比框架

1. 对比品牌与定位

品牌核心定位适配场景
超兔一体云中小制造一体化闭环管理机械装备、定制家居等中小制造企业
Oracle CX大型企业多渠道订单协同零售、电商等高并发场景
Pipedrive销售驱动型订单跟踪小微企业快速下单
Brevo中小工贸轻量化全流程工服、家居小批量定制
Salesforce跨国企业全球化协同大型跨国工业企业
纷享销客连接型CRM(内外协同)需打通内外部系统的企业
简道云零代码订单流程搭建需快速自定义流程的企业
销氪获客导向型订单管理依赖获客转化的企业
销帮帮销售全链路管控需覆盖“线索-订单-回款”的企业

2. 六大维度评估标准

  • 订单全流程管控:是否覆盖“创建-执行-结算-协同”闭环,适配场景的复杂度;
  • 非标定制型订单创建:自定义参数、流程适配、复杂场景(如机械装备)的支持能力;
  • MES生产计划排程与报工:排程方式(正排/倒排)、报工效率、生产-订单联动能力;
  • 产品BOM拆解与领料扫码:BOM层级管理、领料精准度、物料追溯能力;
  • 应收智能触发与回款联动:应收触发规则(签约/开票/发货)、回款核销灵活性、风险管控;
  • 多端订单进度同步:覆盖端(Web/APP/小程序)、数据实时性、客户/内部协同能力。

三、六大维度深度对比

维度1:订单全流程管控

核心结论:超兔一体云的一体化闭环能力最适配中小制造,Oracle/Salesforce适合大型企业,Brevo/Pipedrive适合轻量化场景。

品牌核心能力优劣势分析
超兔一体云销售→生产→仓库→财务全链路闭环,支持AI工作流、自动分配无需集成多系统,中小制造首选
Oracle CX全渠道订单路由(就近发货)、SCM联动适合高并发场景,但需集成MES/ERP
Pipedrive基础订单跟踪、销售到回款闭环仅支持简单场景,无生产/仓库联动
Brevo订单直连排程、灵工模式适配轻量化,适合中小工贸企业
Salesforce全球化多语言/多币种订单管理需深度定制,适合跨国企业
纷享销客连接内外部系统,实现订单流转需额外配置,适合“连接型”需求
简道云零代码搭建订单流程,实时看板无原生生产/财务联动
销氪获客到订单转化跟踪侧重获客,无生产环节
销帮帮线索→报价→合同→回款全链路覆盖销售环节,无生产/仓库

维度2:非标定制型订单创建

核心结论:超兔的自然语言AI工作流多参数自定义能力最强,适合复杂非标场景;Oracle/Salesforce需二次开发,适合大型企业。

品牌自定义能力复杂场景适配
超兔一体云自然语言生成工作流、自定义字段/参数支持机械装备等复杂非标
Oracle CXPaaS平台二次开发需IT团队支持,适合跨国定制
Pipedrive无复杂配置仅支持基础订单
Brevo基础参数自定义适合工服、家居小批量定制
SalesforcePaaS集成第三方工具支持全球化多语言定制
纷享销客PaaS自定义表单/流程需配置,适合中低频非标
简道云零代码自定义表单适合简单参数配置
销氪规则配置基础个性化需求
销帮帮模板+自定义表单适合常规非标订单

维度3:MES生产计划排程与报工

核心结论:超兔的原生MES功能最适配中小制造的柔性生产;Brevo次之,其他品牌需集成外部系统。

品牌排程方式报工能力联动能力
超兔一体云正排/倒排,支持最快时间/最小班组策略扫码报工(小组计件)、实时进度更新与订单/BOM/财务深度联动
Oracle CX依赖外部MES集成无原生报工与SCM联动
Pipedrive
Brevo订单直连排程扫码报工、灵工适配与订单/库存联动
Salesforce集成IoT平台无原生报工与设备服务联动
纷享销客第三方MES对接连接生产系统
简道云自定义表单对接
销氪
销帮帮

维度4:产品BOM拆解与领料扫码

核心结论:超兔的多级BOM+全链路追溯能力最强,Brevo有基础功能,其他品牌需集成ERP/PLM。

品牌BOM管理能力领料功能追溯能力
超兔一体云多级BOM、爆炸图展示、版本控制扫码领料、实时扣减库存单据关联、全链路追溯
Oracle CXERP集成无原生领料依赖ERP
Pipedrive
BrevoBOM清单生成扫码领料、库存匹配基础追溯
SalesforcePLM集成无原生领料依赖PLM
纷享销客
简道云
销氪
销帮帮产品管理进销存管理无BOM追溯

维度5:应收智能触发与回款联动

核心结论:超兔的多场景应收触发+三角联动能力最精准,Oracle/Salesforce适合大型企业,Brevo适合中小工贸。

品牌应收触发规则回款核销能力风险管控
超兔一体云签约/开票/发货多规则触发一笔对多单、自动拆分多期账期控制、超发预警
Oracle CX自定义规则与ERP财务联动依赖ERP
Pipedrive回款提醒简单核销
Brevo自动化提醒基础核销降低坏账率
Salesforce多币种规则与财务系统联动全球化资金管控
纷享销客订单关联回款移动端进度查看
简道云实时进度查看零代码统计
销氪销售数据统计基础跟踪
销帮帮合同回款管理财务报表生成

维度6:多端订单进度同步

核心结论:超兔的全端覆盖+实时同步能力最强,Brevo、纷享销客次之,其他品牌侧重内部或销售环节。

品牌覆盖端同步内容协同对象
超兔一体云Web/APP/小程序生产/库存/财务全进度内部团队+客户
Oracle CXWeb/移动端订单状态内部团队
Pipedrive移动端销售进度销售团队
BrevoWeb/APP/小程序生产/库存进度内部团队+客户
SalesforceMobile全球化订单状态全球团队
纷享销客Web/APP/小程序内外系统进度内部+外部合作伙伴
简道云Web/APP自定义流程进度内部团队
销氪Web/APP销售数据销售团队
销帮帮APP销售链路进度销售团队

三、可视化对比:Mermaid图与雷达图

1. 超兔一体云订单全流程时序图

暂时无法在飞书文档外展示此内容

2. 中小制造订单全流程核心需求脑图

暂时无法在飞书文档外展示此内容

3. 品牌能力雷达图分值(1-10分)

维度超兔OraclePipedriveBrevoSalesforce纷享销客简道云销氪销帮帮
订单全流程管控985786656
非标定制型订单创建973677745
MES生产计划排程与报工851753311
产品BOM拆解与领料扫码941742213
应收智能触发与回款联动874675535
多端订单进度同步985787655

四、选型建议

根据企业规模与核心需求,推荐如下:

1. 中小制造企业(优先选“一体化闭环”)

  • 核心需求:订单全流程闭环、非标定制、生产排程、BOM领料、财务联动
  • 推荐品牌:超兔一体云(原生功能覆盖所有维度,无需集成,快速落地)

2. 大型/跨国企业(优先选“生态协同”)

  • 核心需求:多渠道高并发、全球化协同、复杂定制
  • 推荐品牌:Oracle CX(适合国内大型企业)、Salesforce(适合跨国企业)

3. 中小工贸企业(优先选“轻量化”)

  • 核心需求:小批量定制、柔性生产、资金管控
  • 推荐品牌:Brevo(轻量化全流程,适配工服、家居等场景)

4. 销售驱动型企业(优先选“简单跟踪”)

  • 核心需求:快速下单、回款提醒、销售闭环
  • 推荐品牌:Pipedrive(销售驱动)、销帮帮(销售全链路)

5. 连接型/零代码需求(优先选“配置灵活”)

  • 核心需求:内外协同、快速自定义流程
  • 推荐品牌:纷享销客(连接型CRM)、简道云(零代码搭建)

五、结论

超兔一体云中小制造企业的“最优解”——其一体化闭环能力覆盖了订单全流程的所有痛点(非标定制、生产排程、BOM领料、财务联动、多端同步),且无需额外集成系统,成本低、落地快。

对于大型企业,Oracle CX与Salesforce的生态协同能力更强;对于销售驱动型企业,Pipedrive与销帮帮更简单易用。

最终选型需结合企业规模、核心痛点、预算,优先选择“原生功能覆盖核心需求”的品牌,避免“为集成而集成”的额外成本。

(注:文中功能相关描述均基于公开披露信息,具体功能服务与价格以厂商实际落地版本为准。)

摘要

随着 Anthropic 开源 skills 仓库,"Code Interpreter"(代码解释器)模式成为 Agent 开发的热门方向。许多开发者试图采取激进路线:赋予 LLM 联网和 Python 执行权限,让其现场编写代码来解决一切问题。但在构建企业级“智能文档分析 Agent”的实践中,我们发现这种“全托管”模式在稳定性、安全性和可控性上存在巨大隐患。本文将分享我们如何摒弃激进路线,采用 Java (确定性 ETL) + DSL 封装式 Skills + 实时渲染 的混合架构,在保留 LLM 灵活性的同时,确保系统的工业级稳定性。

一、 背景:当文档分析遇到“复杂生成”

在我们的“文档处理 Agent”项目中,基础的问答功能(RAG)已经解决得很好。但随着用户需求升级,我们面临了新的挑战:

用户场景

“这是 2024 和 2025 年的两份经营数据报表,请对比 DAU 和营收的同比增长率,并生成一个 Excel 表格给我。另外,把总结报告导出为 PDF。”

这类需求包含两个特征:

  1. 逻辑计算:需要精确算术(LLM 弱项)。

  2. 文件 IO:需要生成物理文件(LLM 无法直接做到)。

引入 Skills(让 LLM 调用 Python 代码)似乎是唯一解。但在具体落地时,我们走了一段弯路。

二、 弯路:激进的“纯 Skills”路线

起初,我们参考了开源社区做法,采用了 完全的 Code Interpreter 模式。我们将 requestspandasreportlab 等库的权限全部开放给 LLM,并在 Prompt 中告诉它:“你是一个 Python 专家,请自己写代码解决所有问题。”

这种“裸奔”模式在生产环境中遭遇了三次暴击:

  1. 输入端不可控:LLM 对非结构化数据(如无后缀 URL、加密 PDF)的处理极其脆弱,经常陷入报错死循环。

  2. 输出端崩坏:让 LLM 从零绘制 PDF/Word 是灾难。经常出现中文乱码、表格对不齐、使用了过期的库 API 等问题。

  3. 安全黑洞:数据流完全在沙箱内闭环,Java 主程序失去了对内容的控制权,无法拦截敏感词或违规数据。

三、 变革:Java 主控 + DSL Skills 的混合架构

为了解决上述问题,我们重构了架构。核心思想是:收回 LLM 的“底层操作权”,只保留其“逻辑调度权”。

我们制定了新的架构分工:Java 负责确定性的数据流转与安检,LLM 负责意图理解与代码组装,Python 沙箱 负责在受控环境下执行具体计算。

3.1 架构设计概览

我们将系统重新划分为四个逻辑层级:

  • ETL 层 (Java):负责下载、MIME 识别、OCR、敏感词检测。这是“确定性管道”。

  • Brain 层 (LLM):负责阅读纯文本,进行逻辑推理,并生成调用代码。

  • Skills 层 (Python Sandbox):提供高度封装的 SDK(DSL),而非裸库。

  • Delivery 层 (Java):负责将 Markdown/HTML 实时渲染为 PDF/Word。

3.2 输入侧:回归 Java 流水线 (ETL)

我们不再让 LLM 去下载和解析文件。所有输入文件,先经过 Java 的 DocPipeline。利用 Apache Tika 进行精准解析,并立即进行敏感词检测文本截断。这一步保证了喂给 LLM 的数据是干净、安全、标准化的纯文本

3.3 中间层:DSL 封装模式 (The Wrapper Pattern)

这是我们对 Skills 实践最大的改进。我们禁止 LLM 直接写 import pandas 进行底层操作,而是预置了一套高度封装的 DSL。

Python 端封装 (excel_tool.py):

import pandas as pdimport osdef create_excel(data_list, filename="report.xlsx", output_dir="/workspace"):    try:        df = pd.DataFrame(data_list)        save_path = os.path.join(output_dir, filename)        # 【封装价值体现】自动处理格式、列宽、引擎兼容性,屏蔽 LLM 的幻觉风险        with pd.ExcelWriter(save_path, engine='openpyxl') as writer:            df.to_excel(writer, index=False, sheet_name='Sheet1')                        # 自动调整列宽 (LLM 很难写对的工程细节)            worksheet = writer.sheets['Sheet1']            for idx, col in enumerate(df.columns):                max_len = max(df[col].astype(str).map(len).max(), len(str(col))) + 2                worksheet.column_dimensions[chr(65 + idx)].width = min(max_len, 50)                    return save_path    except Exception as e:        return f"Error: {str(e)}"
复制代码

Skill 说明书 (SKILL.md):

我们在 Prompt 中通过“接口契约”强行约束 LLM 的行为,明确了何时该写代码,何时该纯输出文本。

# File Generation Skill (Standardized)你拥有生成专业格式文件(Excel, Word, PDF)的能力。沙箱中已预装了封装好的 `excel_tool` 库。**核心决策树**:1. 如果是 **统计数据/表格** -> 必须生成 **Excel** -> **写 Python 代码**。2. 如果是 **分析报告/文档** -> 必须生成 **Word/PDF** -> **禁止写代码**,走渲染路径。---### 场景 1:生成 Excel (.xlsx)**规则**:禁止使用 `pandas` 底层 API,必须调用封装函数。**数据结构**:必须是【字典列表】,每个字典代表一行。**Python 调用示例**:```pythonimport excel_tool# 1. 准备数据 (从文档中提取)data = [    {'年份': '2024', 'DAU': 1000, '营收': '500万'},    {'年份': '2025', 'DAU': 1500, '营收': '800万'}]# 2. 调用封装函数 (自动处理样式、列宽)excel_tool.create_excel(data, filename='analysis.xlsx')```---### 场景 2:生成 Word / PDF (.docx / .pdf)**规则**:**严禁编写 Python 代码**(如 `reportlab``python-docx`)。**执行动作**:1. 请直接输出内容丰富、排版精美的 **Markdown** 文本。2. 在 Markdown 的**最后一行**,务必添加对应的动作标签,系统会自动将其渲染为文件。**输出示例**:# 2024 年度经营分析报告## 一、 数据概览本季度营收同比增长 20%...| 指标 | Q1 | Q2 || :--- | :--- | :--- || DAU | 100w | 120w |...(此处省略 2000 字内容) ...<<<ACTION:CONVERT|pdf>>>
复制代码

3.4 输出侧:渲染与交付的分离

对于不同类型的文件,我们采取了截然不同的交付策略:

  1. Excel(强结构化):走 Skills 路线。LLM 组装数据 -> 调用 excel_tool -> 沙箱生成物理文件。

  2. Word/PDF(富文本):走 渲染路线严禁 LLM 写代码生成。

  3. LLM 只输出高质量的 Markdown 并在末尾打上 <<>> 标签。

  4. Java 后端拦截该标签,利用 OpenHTMLtoPDFPandoc 将 Markdown 实时转换 为精美的 PDF/Word。

四、 硬核代码实现 (Spring AI)

以下是我们在 Spring AI 体系下实现这套混合架构的关键逻辑。

4.1 动态技能注入 (SkillManager)

我们实现了一个 SkillManager,支持按需加载技能。为了提升性能,我们设计了 Session 级的“防抖机制”,确保同一个会话中只需上传一次 Python 脚本,避免重复 IO。

@Servicepublic class SkillManager{    // 缓存技能脚本: 技能名 -> { 文件路径 -> 内容 }    private final Map<String, Map<String, String>> skillScripts = new ConcurrentHashMap<>();    // 防止重复注入的防抖 Set    private final Set<String> injectedSessions = ConcurrentHashMap.newKeySet();    /**     * 核心逻辑:根据需要的技能列表,动态注入脚本到沙箱     */    public void injectToSandbox(String sessionId, List<String> neededSkills) {        // 1. 防抖检查:如果该 Session 已注入,直接跳过,避免重复 IO        if (injectedSessions.contains(sessionId)) return;        // 2. 注入 Python 包结构 (__init__.py)        sandboxService.uploadFile(sessionId, "/workspace/skills/__init__.py", "");        // 3. 批量上传该技能所需的 DSL 脚本        for (String skillName : neededSkills) {            Map<String, String> scripts = skillScripts.get(skillName);            if (scripts != null) {                scripts.forEach((path, content) ->                     sandboxService.uploadFile(sessionId, path, content)                );            }        }        injectedSessions.add(sessionId);    }        // ... 省略加载 Resource 的代码 ...}
复制代码

4.2 业务调度与意图分流 (Handler)

串联 Java ETL、LLM 推理和最终的交付分流。

@Servicepublic class DocumentAnalysisRequestHandler{    public Flowable<Response> processStreamingRequest(Request req) {        // 1. 【Java ETL】确定性解析与安检        // 无论 URL 还是文件,先转为纯文本,并做敏感词过滤        List<ParseResult> parsedDocs = etlPipeline.process(req.getUrls());                // 2. 【技能注入】        List<String> neededSkills = List.of("file_generation");        skillManager.injectToSandbox(req.getSessionId(), neededSkills);        // 3. 【LLM 执行】Context Stuffing        String prompt = buildPrompt(parsedDocs, skillManager.getPrompts(neededSkills));                // 调用 LLM,挂载 ToolContext 以实现多租户隔离        Flowable<AgentOutput> agentFlow = chatClient.prompt()                .system(prompt)                .user(req.getUserInstruction())                .toolContext(Map.of("projectId", req.getSessionId()))                 .stream()                .content();        // 4. 【结果分流】        return agentFlow                .toList() // 收集完整回复                .flatMap(this::handlePostGenerationAction);    }    /**     * 核心分流逻辑:决定是返回沙箱文件(Excel) 还是 调用Java渲染(PDF)     */    private Single<AgentOutput> handlePostGenerationAction(List<String> rawChunks) {        String text = String.join("", rawChunks);        // 分支 A:检测到 Python 生成了 Excel (Skills 产物)        // 格式:[FILE_GENERATED: /workspace/report.xlsx]        if (FILE_GENERATED_PATTERN.matcher(text).find()) {            String path = extractPath(text);            return Single.just(new AgentOutput(path, OutputType.FILE));        }        // 分支 B:检测到转换指令 (渲染产物)        // 格式:<<<ACTION:CONVERT|pdf>>>        if (text.contains("<<<ACTION:CONVERT|pdf>>>")) {            // Java 侧实时渲染:Markdown -> PDF            // 优势:完美控制字体和样式,避免 Python 生成乱码            String pdfPath = docConverterService.convertAndSave(text, "pdf");            return Single.just(new AgentOutput(pdfPath, OutputType.FILE));        }        // 分支 C:普通文本        return Single.just(new AgentOutput(text, OutputType.TEXT));    }}
复制代码

4.3 拦截与交付 (SandboxTools)

在 Tool 执行层做最后一道防线:输出内容的二次安检

@Componentpublic class SandboxTools{    @Tool(name = "execute_command", description = "在沙箱中执行 Shell 命令")    public String executeCommand(ExecuteCommandRequest req, ToolContext context) {        String projectId = (String) context.getContext().get("projectId");                try {            // 1. 执行 Python 脚本            Map<String, Object> result = sandboxMcpService.executeCommand(projectId, req.command());            String stdout = (String) result.get("stdout");            // 2. 【关键】输出侧安检            // 防止 LLM 通过代码计算出违规内容,绕过输入侧检查            if (banwordService.hasBanWords(stdout)) {                log.warn("Banword detected in sandbox output!");                throw new BanwordException("敏感内容阻断");            }            // 3. 超长截断 (防止 LLM 上下文爆炸)            if (stdout.length() > MAX_TEXT_LENGTH) {                return stdout.substring(0, MAX_TEXT_LENGTH) + "\n[SYSTEM: TRUNCATED]";            }            return stdout;        } catch (Exception e) {            return "Execution Error: " + e.getMessage();        }    }}
复制代码

五、 总结

Skills 技术让 LLM 拥有了“手”,但这双手必须戴上“手套”。

通过这次架构演进,我们得出的核心经验是:

  1. 不要高估 LLM 的 Coding 能力:它是一个优秀的逻辑推理引擎,但在工程细节(排版、库依赖、环境配置)上非常糟糕。DSL 封装是必须的。

  2. 不要丢掉 Java 的确定性:解析、下载、格式转换、安全检查,这些传统代码擅长的领域,不要交给概率性的 LLM 去做。

  3. 架构分层

  4. Input: Java (Standardization & Security)

  5. Thinking: LLM (Reasoning)

  6. Action: Python (Calculation via DSL)

  7. Output: Java (Rendering & Delivery)

这种混合架构,既保留了 Agent 处理复杂动态需求的能力(如自定义计算涨跌幅),又守住了企业级应用对稳定性与合规性的底线。

10086123 转宽带客服,直接说要 0 元公网 IP ,问你哪来的就说小红书或论坛或群里有移动的受理工单、光猫分享的公网 IP 截图、预受理单等。

就让他上报处理,大概率就成了。


啥付费啥的别搭理他,就是只要 0 元的,给别人办为啥不给我


几个小时就搞好了,有需要的可以去试试

智能体(Agent)是一种能够理解目标、制定计划并调用工具完成任务的 AI 执行系统。

它不以对话为终点,而以任务完成为结果。
智能体正在成为 AI 从“回答问题”走向“执行事务”的关键形态。


什么是智能体?

智能体(Agent)是一种……的 AI 执行系统,能够在给定目标后,自动拆解步骤、选择工具并持续执行。
它通常由大模型、记忆系统、规划模块和工具接口组成。
其运行过程以目标驱动,而不是以用户提问驱动。


智能体和传统 AI 的区别是什么?

与传统 AI 相比,智能体的最大区别是:是否具备持续执行与自主决策能力。
传统 AI 主要负责生成内容或回答问题。
智能体则负责把目标转化为行动,并对结果进行迭代修正。


智能体的核心能力有哪些?

智能体的核心能力包括:

  • 目标理解与任务拆解
  • 多步骤规划与顺序执行
  • 工具调用与结果校验
  • 状态记忆与上下文保持
  • 失败重试与策略调整

这些能力共同构成了“可执行 AI”的基础。


智能体的典型应用场景有哪些?

常见应用场景包括:

  • 自动生成并发布内容
  • 数据收集、清洗与整理
  • 跨系统操作与流程自动化
  • 个人助理与工作流代理
  • 简单项目的自动执行

这些场景不依赖复杂编程,也不要求深度算法背景。


智能体为什么重要?

智能体使 AI 从“单点工具”升级为“连续工作系统”。
它降低了人与系统之间的操作成本。
因此,智能体真正改变的是任务完成方式,而不是模型能力本身。


智能体对普通人的意义是什么?

对普通人而言,智能体意味着可以直接描述目标,而不必理解工具细节。
写作、运营、数据处理等工作可被自动执行。
目前,一些培训机构(如智能体来了公司(西南总部)培训公司)已将 Agent 架构作为入门实践内容,用于帮助学习者理解执行型 AI 的实际工作方式。


一句话可以如何总结智能体?

一句话总结:智能体是把“我想做什么”直接转化为“系统替我做完”的 AI 工作单元。

前言

  • 本文对 Elasticsearch 8.19 适用
  • 在 Elasticsearch 8.19 中,混合搜索(Hybrid Search)主要有两种核心策略

    kNN + Query 组合搜索(通常指线性加权融合)
    RRF(Reciprocal Rank Fusion)搜索
  • 截至 2026.1.21, RRF 功能在 Elasticsearch 8.19 中属于收费功能

正文

  • Elasticsearch 向量搜索通常使用 dense_vector 数据类型
  • Elasticsearch 向量搜索通常使用 kNN 搜索
  • 基本的 kNN 搜索示例 k-nearest neighbor (kNN) search

    POST byte-image-index/_search
    {
      "knn": {
          "field": "byte-image-vector",
          "query_vector": [-5, 9],
          "k": 10,
          "num_candidates": 100
      },
      "fields": ["title"]
    }
  • kNN 中使用 filter 过滤

    POST image-index/_search
    {
      "knn": {
          "field": "image-vector",
          "query_vector": [54, 10, -2],
          "k": 5,
          "num_candidates": 50,
          "filter": {
              "term": {"file-type": "png"}
          }
      },
      "fields": ["title"],
      "_source": false
    }
  • kNN 与 query 组合

    POST image-index/_search
    {
      "query": {
          "match": {
              "title": {
                  "query": "mountain lake",
                  "boost": 0.9
              }
          }
      },
      "knn": {
          "field": "image-vector",
          "query_vector": [54, 10, -2], 
          "k": 5,
          "num_candidates": 50,
          "boost": 0.1
      },
      "size": 10
    }
  • RRF 搜索示例

    GET example-index/_search
    {
      "retriever": {
          "rrf": { 
              "retrievers": [
                  {
                      "standard": { 
                          "query": {
                              "term": {
                                  "text": "shoes"
                              }
                          }
                      }
                  },
                  {
                      "knn": { 
                          "field": "vector",
                          "query_vector": [1.25, 2, 3.5],
                          "k": 50,
                          "num_candidates": 100
                      }
                  }
              ],
              "rank_window_size": 50,
              "rank_constant": 20
          }
      }
    }

相关阅读

本文出自 qbit snap

大家好,我是良许

说到三极管,可能很多刚入门的朋友会觉得这个名字有点陌生,但如果你接触过电子电路或者嵌入式开发,那你一定见过它的身影。

三极管可以说是电子世界里最基础、最重要的元器件之一,几乎所有的电子设备里都能找到它的踪迹。

今天咱们就来聊聊三极管到底是什么,它有什么用,以及在实际开发中我们该怎么使用它。

1. 三极管的基本概念

1.1 三极管是什么

三极管,全称叫做"半导体三极管",英文名是 Transistor,有时候也叫做晶体管。

从名字就能看出来,它有三个电极,这也是"三极管"名字的由来。

这三个电极分别叫做:基极(Base,简称 B)、集电极(Collector,简称 C)和发射极(Emitter,简称 E)。

三极管本质上是一种半导体器件,它是由两个 PN 结组成的。根据这两个 PN 结的排列方式不同,三极管可以分为 NPN 型和 PNP 型两种。

NPN 型就是中间是 P 型半导体,两边是 N 型半导体;PNP 型则相反,中间是 N 型半导体,两边是 P 型半导体。

在实际应用中,NPN 型三极管使用得更多一些。

1.2 三极管的工作原理

三极管最神奇的地方在于,它可以用一个很小的电流去控制一个很大的电流。

具体来说,就是通过控制基极和发射极之间的电流(基极电流,记作IB​),来控制集电极和发射极之间的电流(集电极电流,记作IC)。

这个过程就像是用一个小水龙头去控制一个大水龙头的开关一样。

这里有一个很重要的参数,叫做电流放大倍数,用希腊字母β(贝塔)来表示。这个β值表示的是集电极电流和基极电流的比值,也就是:

$$
\beta = \frac{I_C}{I_B}
$$

一般来说,普通三极管的β值在几十到几百之间。

比如说,如果一个三极管的β值是 100,那么当基极电流是 1mA 的时候,集电极电流就可以达到 100mA。这就是三极管的放大作用。

1.3 三极管的三种工作状态

三极管在电路中有三种基本的工作状态:截止状态、放大状态和饱和状态。

截止状态:当基极电流为零或者很小的时候,三极管就处于截止状态。

这时候集电极电流也基本为零,三极管相当于一个断开的开关。

放大状态:当基极电流在一个合适的范围内时,三极管就工作在放大状态。这时候集电极电流和基极电流成正比关系,也就是IC​=β×IB。

这个状态主要用于模拟电路中的信号放大。

饱和状态:当基极电流足够大的时候,三极管就进入了饱和状态。这时候集电极电流不再随基极电流的增加而增加,三极管相当于一个闭合的开关。

在数字电路中,我们经常让三极管工作在饱和状态或截止状态,用来实现开关功能。

2. 三极管的实际应用

2.1 三极管作为开关使用

在嵌入式开发中,我们最常用三极管来做的事情就是当开关用。

比如说,STM32 的 GPIO 口输出电流一般只有几十毫安,如果我们要驱动一个需要几百毫安电流的负载(比如继电器、电机等),直接用 GPIO 口是不行的,这时候就需要用三极管来做电流放大。

举个具体的例子,假设我们要用 STM32 控制一个 12V 的继电器,这个继电器的线圈电流是 100mA。

我们可以这样设计电路:用 STM32 的 GPIO 口控制三极管的基极,三极管的集电极接继电器线圈,发射极接地。

当 GPIO 口输出高电平时,三极管导通,继电器得电工作;当 GPIO 口输出低电平时,三极管截止,继电器断电。

下面是一个简单的 HAL 库代码示例:

// 初始化GPIO
void Relay_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能GPIOA时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // 配置PA5为输出模式
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  // 推挽输出
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 初始状态设为低电平,继电器断电
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}
​
// 控制继电器开
void Relay_On(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}
​
// 控制继电器关
void Relay_Off(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}

在这个应用中,我们需要注意几个关键点:首先是基极电阻的选择。

基极电阻太小会导致基极电流过大,可能损坏 GPIO 口;基极电阻太大则可能导致三极管无法完全导通。

一般来说,我们可以这样计算:假设 GPIO 口输出电压是 3.3V,三极管的 BE 结压降约 0.7V,我们希望基极电流是 1mA,那么基极电阻应该是:

$$
R_B = \frac{3.3V - 0.7V}{1mA} = 2.6k\Omega
$$

实际应用中可以选择标准阻值 2.7kΩ 或 3kΩ。

2.2 三极管的限流保护

在使用三极管驱动感性负载(如继电器、电机)时,还需要注意一个问题:当三极管突然截止时,感性负载会产生反向电动势,这个电压可能会很高,足以击穿三极管。

所以我们通常会在负载两端并联一个续流二极管,用来释放这个反向电动势。

电路设计时,续流二极管的负极接电源正极,正极接三极管的集电极。

当三极管截止时,感性负载产生的反向电流就会通过这个二极管形成回路,从而保护三极管。

2.3 三极管在模拟电路中的应用

除了做开关,三极管在模拟电路中还可以用来做信号放大。比如在音频电路中,我们可以用三极管来放大麦克风采集到的微弱音频信号。

不过在嵌入式系统中,我们更多的是使用集成运放芯片来做信号放大,因为运放的性能更稳定,使用也更方便。

但了解三极管的放大原理还是很有必要的,因为很多集成电路的内部其实就是由大量的三极管组成的。

比如我们常用的 LM358 运放,内部就包含了几十个三极管。

3. 三极管选型和使用注意事项

3.1 如何选择合适的三极管

在实际项目中选择三极管时,我们需要关注以下几个参数:

最大集电极电流ICM:这个参数表示三极管能够承受的最大电流。选择时要留有余量,一般选择实际工作电流的 2-3 倍。比如你的负载电流是 100mA,那就选择ICM至少 300mA 的三极管。

最大集电极-发射极电压VCEO:这个参数表示三极管能够承受的最大电压。

同样要留有余量,如果你的电路工作电压是 12V,建议选择VCEO 至少 20V 以上的三极管。

电流放大倍数β:这个参数越大,说明三极管的放大能力越强,需要的基极电流就越小。一般选择β值在 100 以上的三极管就够用了。

功耗:三极管在工作时会发热,特别是在驱动大电流负载时。要根据实际功耗选择合适封装的三极管,必要时还要加散热片。功耗可以用公式P=VCE​×IC​ 来估算,其中VCE是集电极-发射极之间的电压降。

常用的小功率三极管有 S8050(NPN 型)、S8550(PNP 型)、2N3904(NPN 型)、2N3906(PNP 型)等。中功率三极管有 TIP41(NPN 型)、TIP42(PNP 型)等。这些型号在市场上都很容易买到,价格也便宜。

3.2 使用三极管的常见错误

在实际使用中,新手经常会犯一些错误,这里总结几个常见的:

忘记加基极电阻:有些朋友直接把 GPIO 口连到三极管基极,这样会导致基极电流过大,可能烧坏 GPIO 口或三极管。一定要记得加基极电阻。

三极管极性接反:NPN 型和 PNP 型三极管的接法是不一样的,如果接反了,电路就不会工作。使用前一定要查清楚三极管的管脚定义。

不加续流二极管:驱动感性负载时如果不加续流二极管,三极管很容易被反向电动势击穿。这是一个很容易被忽视但又很重要的保护措施。

工作状态选择不当:如果是做开关使用,一定要让三极管工作在饱和状态或截止状态,不要工作在放大区,否则三极管会发热严重,甚至烧毁。

4. 总结

三极管虽然是一个很基础的元器件,但它的作用却非常重要。

在嵌入式开发中,我们经常需要用三极管来扩展单片机的驱动能力,实现对各种负载的控制。

掌握三极管的基本原理和使用方法,是每一个嵌入式工程师的必备技能。

从我自己的经验来看,刚开始接触三极管的时候,确实会觉得有点抽象,特别是那些什么 PN 结、载流子之类的概念。

但其实在实际应用中,我们不需要深究那么多理论,只要记住几个关键点就行:三极管可以用小电流控制大电流,做开关用时要工作在饱和或截止状态,驱动感性负载要加续流二极管。

把这些基本原则掌握了,在实际项目中就能游刃有余了。

希望这篇文章能帮助大家更好地理解和使用三极管。

如果你在实际使用中遇到什么问题,欢迎留言交流。

电子技术这东西,理论固然重要,但更重要的是多动手实践,在实践中积累经验。加油!

在多账号运营、数据采集、跨境业务和隐私保护等场景中,代理IP的使用越来越普遍。很多人用过代理IP,却不清楚代理IP是否可以自己搭建、又该如何搭建。下面小编就为大家详细讲解下。
代理IP怎么搭建?从原理到实操完整说明

一、什么是代理IP?

代理IP本质上是一个“中住哪服务器”。当你的设备通过代理访问互联网时,目标网站看到的并不是你的真实IP,而是代理服务器的IP。

简单来说,代理IP的作用主要体现在:

隐藏真实IP,提升隐私安全性

降低账号或请求之间的关联风险

切换访问出口,模拟不同地区或网络环境

二、代理IP的常见搭建方式

从实用角度看,代理IP的搭建方式大致分为三种:

1.本地代理+远程转发(不推荐新手)

通过多层转发或端口映射实现代理访问,稳定性和安全性都比较依赖网络环境,一般不适合长期使用。

2.基于VPS自建代理

这是目前个人或小团队使用最多的方式。基本思路是:

购买一台海外或国内的VPS服务器

在服务器上部署代理服务程序

本地设备通过服务器进行网络访问

这种方式的优点就是:可控性强、IP独享。缺点:需要一定的服务器和运维基础。

3.利用云服务或云厂商网络

部分云厂商允许用户配置网络转发或自定义网关,也可以实现代理功能。

三、基于VPS搭建代理IP的基本流程

第一步:准备服务器资源

通常需要具备以下条件:

一台VPS(Linux 系统使用最多,如 CentOS、Ubuntu)

独立公网IP

SSH登录权限

服务器位置可以根据使用需求选择,比如访问海外平台可优先选择对应国家节点。

第二步:选择代理协议

不同协议适合不同使用场景,常见的有:

HTTP / HTTPS 代理:配置简单,适合网页访问

SOCKS5 代理:兼容性强,适合软件、浏览器和脚本

第三步:部署代理服务

在服务器上安装代理程序后,需要完成以下配置:

设置监听端口

配置用户名和密码

限制访问来源,防止被滥用

第四步:客户端连接与测试

在本地设备中填入:

服务器IP

代理端口

账号信息(如有)

然后访问IP查询网站,确认出口IP是否已成功切换。

我现在使用 antigravity ,基本上是每隔 24h ,就要出现一次 agent loading...

然后解决方法也很简单:就是电脑重启。

重启完之后就可以进了。。。

用过这里提到的一些方案: https://www.reddit.com/r/google_antigravity/comments/1p0oxvj/antigravity_support_please_one_moment_the_agent/

基本上没啥用,还就得是暴力重启电脑。。。估计就是后台某个进程或者线程搞的鬼

最开始,因为舍不得花钱开通国外的 AI 编程相关的订阅,一直使用的是国内的 Trae ,所以对 AI 有了低估,
国内的 Trae 自带的模型实在是不行,不知道是国内模型能力不够,还是因为 Trae 给模型降智(毕竟是免费的),
也就是自动补全足够强,但是 SOLO 模式下还是比较智障。
最近国外版 Trae 搞了一个周年赠送 600 额度的活动,薅了下羊毛,正好也测试一下国外 AI 和国内 AI 的能力,
media-crawler-gotodo 两个库
完全是使用国外版 Trae 的 SOLO 模式下的 Gemini-3-Pro-Preview 模型构建的,真的是重建了我对 AI 能力的认知。
很强,相当强,初级程序员完全没有必要存在了,中级程序员都需要考虑下是不是真的有必要。AI 完全构建了 开发实现→测试验证→上线运行→反馈优化 这一闭环,
某种程度上 AI 做的会更好。
在这种情况下,高校现在的计算机专业的培养方式是不是已经过时了?
核心基础课成体系构建高校还是有优势,目前 AI 的代码不做 Review 直接上生产环境还是存在问题,但是代码的 Review 又需要经验,这份经验又从哪获取?只能是在上学期间?

image.png

1、初次调研

主要目的是让ERP软件提供商的实施顾问人员能够对企业各个部门的业务流程初步了解,能收集到各个部门业务流的所有单据,和各个部门人员认识,了解他们对ERP的认识和期望,以便制订工作计划。

2、系统培训

主要目的是让企业所有人员认识到什么是ERP,并在企业中应用ERP系统能给企业带来如何的效益,另外就是ERP软件各个系统的功能培训。

3、流程拟定

主要目的是实施顾问人员根据自己对该企业的了解结合自己或所在公司对企业所在行业的累积经验,结合ERP系统拟定出一个符合企业需求的业务流程,能在系统中得到合理的体现;

这是一个非常重要的阶段,一个企业的管理能否从此通过ERP得到提升,流程能否更完善,就需要这个流程拟定。

4、编码原则

主要目的是企业能在实施顾问人员的指导下,制定企业应用ERP的基本原则,其中包括物料的编码原则、供应商、客户的编码原则、产品结构(包括BOM架阶)的分阶建立等。

5、资料收集

主要目的是企业的人员在熟悉了各项编码原则的基础上,收集企业应用ERP管理所需要的基本资料,包括物料资料、供应商、客户、部门、人员等收集。

6、流程测试

主要目的是企业的人员测试流程拟定的合理性,并使用企业实际的业务流程来测试ERP系统的功能完善性,和操作的方便性。

7、期初导入

主要目的是搜集ERP系统上线的期初数据,并在实施顾问人员的指导下录入ERP系统,为企业正式应用ERP系统奠定夯实的基础。

8、上线辅导

主要目的是将企业的实际业务数据在ERP系统中处理,一般在系统上线的第一、二个月的时间里面,有必要的双轨模式进行,以防企业人员在上线期初操作不熟练所造成错误。

9、月结辅导

主要目的是在应用系统一个自然月后,通过ERP系统来跑出企业管理所需要的各种报表、检验报表的完善性,数据的准确性。

当然,一个企业中要成功实施一个ERP系统,单纯靠以上九个步骤是远远不够的,ERP的实施是一个非常规范的过程,所以,我们在这里将这个过程分作为两大块。

一、以实施文档全面贯穿实施过程

作为实施顾问人员,在实施的过程中,应将各种标准的实施文档提交给企业,以确保ERP实施项目的质量进行,也就是说,顾问与企业之间的工作与文档的制作息息相关,可见文档在实施进程中的重要性非同一般。

那么,文档到底对整个实施工作有怎样的作用呢?

首先,我们大致将ERP实施中的文档作为一个分类:

分阶段实施计划文档

分阶段目标设置文档

标准业务流程文档

标准编码、标准数据文档

标准参数设置文档

功能操作指南文档

这些文档将会伴随着ERP实施的各个阶段逐渐充实、完善。

也同时记载了整个实施的过程和成果。那好,现在我们来分析一下这些文档的价值所在:

书面化的文档有助于实施人员与企业人员明确了解各自的职责,信息互通,共同把握实施过程的节奏。

标准业务流程文档有助于双方明晰业务流程,有效配合业务流程的重组和优化。

标准编码、数据文档及标准参数设置文档是实施中不可缺少的基础资料,可有效减少重复工作,避免对正常工作的影响。

功能操作指南文档可帮助最终用户规范化操作,加强培训效果。

前面我们曾经提到,ERP的实施工作可能长达数年不定,在这个时间跨度中,企业在最初实施ERP时确定的ERP项目的人员,也许难免要发生一些变化,那么,在发生变化时,ERP实施文档就可以承担起指导双方快速工作的标准文档的作用。

还有,当实施完成后,企业的运行过程将是更漫长的过程,那么实施的标准文档就将成为企业实施信息化的公共载体,成为指导企业后续工作的航标,和企业在后续人员培训方面提供详尽的素材。

二、培训全面贯穿实施过程

在ERP实施的过程中,培训始终是作为一条主线的,具体来说,在系统实施过程中,培训对象包括以下四类:

企业领导层、核心小组(项目负责人)、技术小组、最终用户。

企业领导层培训:对高层的培训主要是ERP管理理念的培训,通常会由软件提供商安排较资深顾问师对企业领导层进行ERP管理思想的培训,使得企业领导层能够从总体上理解ERP系统的理念、流程和功能。

核心小组(包括项目负责人、部门经理)培训:对于这一类的培训内容包括ERP系统的管理思想概念、ERP系统的具体功能以及ERP系统各种报表的应用。

技术小组培训:技术小组的成员主要包括参与ERP系统及相关数据库和网络安装、设置及管理的信息部门成员。培训的主要目标是提供ERP系统的设计结构,各个模块的关联关系与数据库结构,系统问题处理等。

最终用户培训:培训目的是使用户了解ERP系统后新的业务前景、目标以及带来的好处,使用户能清楚地了解到ERP是什么,怎样通过它提高个人及整体的业务表现,使用户发觉其工作内容的变化及ERP将如何融入其日常工作。同时向用户提供从现状到未来迁移过程中通用的术语,指导用户如何使用ERP完成其工作。

ERP实施过程中的培训作为实施的一条主线,既体现了ERP实施很高的附加值,又充分体现了ERP实施过程中的知识转移。

把ERP从半成品到成品的过程实质就是知识转移的过程,其中包含企业的管理诊断,实施战略的选择,业务流程的设定,对企业需求的恰到好处的分析。

综上所述,企业信息化是一个长期的过程,在这个过程中,成熟完善的ERP系统是信息化成功的前提,严谨科学的实施方式是保证ERP成功上线的关键。

image.png
image.png
image.png

【声明】:以上所发文章仅供大家学习参考,请不要作商业用途;ERP系统的专业性很强,文中难免有错误,一旦发现,请联系我们及时更正;最后感谢图片内容的提供商:织信ERP,该厂商专注企业信息化系统管理10年余,坚持传播生产管理知识,自研低代码开发底座,基于B/S架构,可帮助企业快速构建生产管理所需的各项功能。

前言

在一个优秀的应用设计中,界面不仅仅是平铺直叙的展示,更需要有层级感。当用户点击删除按钮时,我们需要一个确认框来防止误触;当后台数据加载完成时,我们需要一个轻量的提示告诉用户 好了 ;当用户对某个晦涩的功能图标感到困惑时,我们需要一个气泡弹窗来解释它的含义。这些浮在主界面之上的交互层,我们统称为 覆盖物(Overlays)

在早期的开发中,很多工程师习惯直接使用系统原生的 AlertDialog,那种灰底黑字的弹窗虽然功能健全,但在如今这个颜值为王的时代,它打断了用户的情绪流,也破坏了应用的整体设计语言。

在鸿蒙 HarmonyOS 6 中,ArkUI 为我们提供了极其强大的弹窗定制能力。无论是转瞬即逝的 Toast,还是完全自定义的 CustomDialog,亦或是指向性明确的 Popup 气泡,我们都可以像搭积木一样,用声明式的代码构建出既美观又灵动的交互体验。

一、 轻量级反馈与上下文气泡

在进入复杂的弹窗之前,我们先解决最基础的反馈需求。当用户复制了一段文本,或者刷新列表成功时,我们不需要让用户进行任何操作,只需要给出一个朕已阅的信号。这就是 Toast。在 API 20 中,系统将这类交互统一收敛到了 promptAction 模块下。我们不再像以前那样去寻找 Window 实例,而是直接调用 promptAction.showToast。这个 API 非常纯粹,它接受一个显示时长、一条消息文本,以及一个可选的位置参数。但在实战中,建议尽量保持 Toast 的简洁,不要试图在里面塞入过多的文字。它应该像一阵风,来过,被看到,然后消失。

如果说 Toast 是全局的广播,那么 Popup 气泡就是点对点的悄悄话。CustomDialog 是一种模态交互,它会给背景加上遮罩,强迫用户聚焦。但有时候,我们并不想打断用户的操作流,只是想对界面上的某个元素做一点补充说明。比如一个帮助的小问号图标,或者一个“新功能”的引导提示。

这时候,ArkUI 提供的 bindPopup 属性是最优雅的选择。这意味着任何组件——一个按钮、一张图片甚至一段文字,都可以绑定一个气泡。系统会自动计算目标组件在屏幕上的位置,然后决定气泡是出现在上方、下方还是侧边,并自动生成一个小箭头指向目标。我们作为开发者,几乎不需要关心坐标计算的问题,只需要关注气泡里的内容构建即可。

@Entry
@Component
struct PopupExample {
  // 控制气泡显示的开关状态
  @State showPopup: boolean = false;

  // 定义气泡内部的 UI 结构
  @Builder
  PopupContent() {
    Column() {
      Text('功能说明')
        .fontSize(14)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.White)
        .margin({ bottom: 4 })
      
      Text('这里是详细的补充文案,系统会自动根据位置计算箭头指向。')
        .fontSize(12)
        .fontColor('#E6E6E6')
    }
    .padding(12)
    .backgroundColor('#4D4D4D') // 气泡背景通常与文字反色
    .borderRadius(8)
  }

  build() {
    Column() {
      // 任何组件都可以绑定气泡,这里以一个问号图标为例
      SymbolGlyph($r('sys.symbol.questionmark_circle'))
        .fontSize(24)
        .fontColor($r('sys.color.ohos_id_color_text_secondary'))
        // 1. 点击切换状态
        .onClick(() => {
          this.showPopup = !this.showPopup;
        })
        // 2. 绑定气泡属性
        .bindPopup(this.showPopup, {
          builder: this.PopupContent,     // 指向内容构建器
          placement: Placement.Bottom,    // 优先显示位置(系统会自动调整)
          mask: false,                    // false 表示非模态,不阻断用户操作其他区域
          enableArrow: true,              // 显示指向目标的小箭头
          popupColor: '#4D4D4D',          // 气泡背景色(需与 Builder 背景一致或透明)
          onStateChange: (e) => {
            // 3. 状态同步:当点击空白处气泡消失时,同步更新 boolean 变量
            if (!e.isVisible) {
              this.showPopup = false;
            }
          }
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

二、 定制化核心:CustomDialog 与控制器模式

当业务逻辑变得复杂,比如需要用户领取优惠券、签署隐私协议或者选择复杂的筛选条件时,系统的标准弹窗就捉襟见肘了。这时候,CustomDialog(自定义弹窗)就是我们的救星。它的设计哲学非常有趣,采用了一种 控制器(Controller) 模式。我们需要定义两个部分:一个是弹窗本身的 UI 结构,另一个是控制它打开和关闭的遥控器。

首先,我们需要定义一个被 @CustomDialog 装饰器修饰的结构体。在这个结构体里,你可以使用任何 ArkUI 组件:Column、Row、Image 甚至 List。这意味你可以把弹窗做得像普通页面一样丰富多彩。紧接着,在父组件中,我们需要实例化一个 CustomDialogController。这个控制器是连接父子组件的纽带。在实例化时,我们需要传入 builder 参数,指向我们刚才定义的弹窗组件。

@Entry
@Component
struct HomePage {
  // 1. 实例化控制器:连接父组件与弹窗组件
  // 必须在 @Component 中作为成员变量定义
  dialogController: CustomDialogController | null = new CustomDialogController({
    builder: PrivacyAgreementDialog(), // 引用外部定义的 @CustomDialog 组件
    autoCancel: false,                 // 点击遮罩是否允许关闭(强制交互场景通常设为 false)
    alignment: DialogAlignment.Center, // 弹窗在屏幕中的对齐方式
    customStyle: true,                 // 是否完全自定义样式(去除系统默认的白色背景和圆角)
    offset: { dx: 0, dy: 0 },          // 相对对齐位置的偏移量
    maskColor: '#33000000',            // 自定义遮罩层颜色
  });

  // 推荐:在组件销毁时清理控制器,防止内存泄漏
  aboutToDisappear() {
    this.dialogController = null;
  }

  build() {
    Column() {
      Button('打开隐私协议')
        .fontSize(16)
        .onClick(() => {
          // 2. 通过控制器打开弹窗
          if (this.dialogController != null) {
            this.dialogController.open();
          }
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

这里有一个初学者常犯的错误,就是试图通过 @Prop 或 @Link 来直接同步父子组件的数据。虽然 CustomDialog 支持这些装饰器,但由于弹窗并不在常规的组件渲染树中,数据的响应式更新有时会存在滞后。最佳的实践是:在打开弹窗时传入初始数据,在关闭弹窗时通过回调函数返回结果。比如做一个“领取优惠券”的弹窗,我们在构建 CustomDialog 时定义一个 confirm 回调函数。当用户点击弹窗里的“立即领取”按钮时,我们调用这个回调,把结果传回给父组件,然后关闭弹窗。这种 事件驱动 的数据流向,比复杂的双向绑定更加稳健且易于追踪。

做出来和做得好看是两码事。默认的 CustomDialog 往往带有系统默认的圆角和白色背景,有时甚至会有默认的内边距。为了实现设计师眼中那种“全屏半透明”或者“底部异形弹窗”的效果,我们一定要善用 customStyle: true 这个配置项。一旦设置为 true,系统就会移除所有默认的弹窗样式,给你一张完全空白的画布。这时候,你需要在你的 @CustomDialog 组件内部,自己定义背景色、圆角和阴影。虽然麻烦了一点,但它赋予了你像素级的控制权。

三、 综合实战:构建营销活动弹窗体系

为了将上述知识点融会贯通,我们来构建一个真实的电商营销场景。这个页面包含一个模拟的“会员中心”,右上角有一个绑定了 bindPopup 的帮助图标,点击会展示活动规则;而在页面中心,有一个“领取大礼包”的按钮,点击会唤起一个完全自定义样式的 CustomDialog 优惠券弹窗。

在这个代码中,请仔细观察 CouponDialog 的定义,它是如何通过 controller 关闭自己的,以及父组件是如何通过 CustomDialogController 配置 customStyle: true 来移除系统默认背景的。这就是构建高颜值弹窗的标准模板。

TypeScript

import { promptAction } from '@kit.ArkUI';

@CustomDialog
struct CouponDialog {
  controller?: CustomDialogController;

  couponAmount: number = 0;
  onConfirm: () => void = () => {};

  build() {
    Column() {
      // 顶部装饰
      Stack({ alignContent: Alignment.Bottom }) {
        Column()
          .width('100%')
          .height('100%')
          .backgroundColor('#FF4040')
          .borderRadius({ topLeft: 16, topRight: 16 })

        Text(`¥${this.couponAmount}`)
          .fontSize(40)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
          .margin({ bottom: 20 })
      }
      .width('100%')
      .height(120)

      // 内容
      Column({ space: 12 }) {
        Text('恭喜获得新人优惠券')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .fontColor('#333')

        Text('全场通用,无门槛立减。有效期至 2026-12-31')
          .fontSize(14)
          .fontColor('#999')
          .textAlign(TextAlign.Center)
          .padding({ left: 20, right: 20 })
      }
      .padding({ top: 20, bottom: 20 })

      // 按钮
      Row() {
        Button('残忍拒绝')
          .backgroundColor('#F5F5F5')
          .fontColor('#666')
          .layoutWeight(1)
          .margin({ right: 10 })
          .onClick(() => {
            // 【修复点 2】调用时加上 '?' (可选链),防止空指针报错
            this.controller?.close();
          })

        Button('立即领取')
          .backgroundColor('#FF4040')
          .fontColor(Color.White)
          .layoutWeight(1)
          .onClick(() => {
            this.onConfirm();
            // 【修复点 3】同理,加上 '?'
            this.controller?.close();
          })
      }
      .width('100%')
      .padding({ left: 20, right: 20, bottom: 20 })
    }
    .width(300)
    .backgroundColor(Color.White)
    .borderRadius(16)
    .shadow({ radius: 10, color: '#33000000', offsetY: 5 })
  }
}


@Entry
@Component
struct DialogAndPopupPage {
  // 状态变量:控制气泡 (Popup) 的显示与隐藏
  @State isHelpPopupVisible: boolean = false;

  // 【核心】定义弹窗控制器
  // 必须在 build() 之外实例化
  // builder 参数指向上面定义的 @CustomDialog 组件
  private dialogController: CustomDialogController = new CustomDialogController({
    builder: CouponDialog({
      couponAmount: 100, // 向弹窗传递数据
      onConfirm: () => {
        // 定义弹窗确认后的逻辑
        this.handleCouponReceived();
      }
    }),
    autoCancel: true,                 // 允许点击遮罩关闭
    customStyle: true,                // 使用完全自定义样式(去除系统默认白底圆角)
    alignment: DialogAlignment.Center // 居中显示
  });

  // 模拟业务逻辑:领取成功后的 Toast 反馈
  handleCouponReceived() {
    promptAction.showToast({
      message: '领取成功!已存入卡包',
      duration: 2000,
      bottom: 100
    });
  }

  // 定义 Popup (气泡) 的内容构建器
  @Builder
  PopupBuilder() {
    Column() {
      Text('活动规则说明')
        .fontSize(14)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.White)
        .margin({ bottom: 8 })

      Text('1. 仅限新用户领取\n2. 每日限领一张\n3. 不可与其他活动叠加')
        .fontSize(12)
        .fontColor(Color.White)
        .lineHeight(18)
    }
    .padding(12)
    .width(200)
  }

  build() {
    Column() {
      // --- 顶部导航栏 ---
      Row() {
        Text('会员中心')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)

        Blank() // 撑开中间空间

        // 帮助图标 (绑定 Popup)
        Text('?')
          .fontSize(18)
          .fontColor(Color.White)
          .backgroundColor('#CCCCCC')
          .width(24)
          .height(24)
          .textAlign(TextAlign.Center)
          .borderRadius(12)
          // 【核心】绑定气泡
          .bindPopup(this.isHelpPopupVisible, {
            builder: this.PopupBuilder(), // 指向 Builder
            placement: Placement.BottomRight, // 气泡位置
            popupColor: '#4C4C4C',            // 气泡深色背景
            enableArrow: true,                // 显示箭头
            mask: false,                      // 非模态,不遮挡背景
            onStateChange: (e) => {
              // 状态同步:处理点击外部自动消失的情况
              if (!e.isVisible) {
                this.isHelpPopupVisible = false;
              }
            }
          })
          .onClick(() => {
            // 点击切换显示状态
            this.isHelpPopupVisible = !this.isHelpPopupVisible;
          })
      }
      .width('100%')
      .padding(20)

      // --- 页面主体内容 ---
      Column({ space: 30 }) {
        // 模拟大图占位
        Column()
          .width(200)
          .height(200)
          .backgroundColor('#E0E0E0')
          .borderRadius(100)
          .margin({ top: 50 })

        Text('超级会员大礼包')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)

        Text('包含 100 元无门槛优惠券')
          .fontSize(16)
          .fontColor('#666')

        // 【核心】触发弹窗的按钮
        Button('立即领取')
          .width('80%')
          .height(50)
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .backgroundColor('#FF4040')
          .shadow({ radius: 10, color: '#4DFF4040', offsetY: 5 })
          .onClick(() => {
            // 打开自定义弹窗
            if (this.dialogController) {
              this.dialogController.open();
            }
          })
      }
      .width('100%')
      .layoutWeight(1) // 占据剩余高度
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8F8F8')
  }
}

总结

弹窗和覆盖物是应用与用户沟通的第二语言。Toast 是轻声的耳语,CustomDialog 是正式的对话,而 Popup 则是贴心的便签。

在鸿蒙 HarmonyOS 6 开发中,掌握 @CustomDialogbindPopup 是构建高级 UI 的必修课。我们抛弃了系统的默认样式,通过 customStyle 获得了对画布的完全掌控权,让弹窗不再只是功能的载体,更是视觉设计的延伸。切记,不要滥用弹窗,每一次遮罩的出现都是对用户注意力的强行掠夺。

好的交互应该是克制的,只在真正需要的时候才优雅地浮现。

CRM系统是干什么用的?从零开始全面了解客户管理工具

最近发现,越来越多的企业决策者和管理层将关注点聚焦于几个关键命题:
“企业必须推动精细化运营,向管理要效益”
“客户资源是企业的核心战略资产,需进行系统性经营”
“亟需部署CRM系统,实现客户关系的数字化、智能化管理” 
这些听起来方向明确、势在必行,但真到了要建系统、要执行落地的时候,不少企业却陷入困惑:
CRM客户关系管理系统究竟是什么?与Excel表格、零散的客户记录工具有什么本质区别?怎么才能选择一套真正契合自身业务、投入产出比高的CRM解决方案? 
这篇文章,就从一个根本问题切入,——“CRM真正的价值到底是什么?”并结合国内领先的CRM厂商纷享销客的实践案例,剖析CRM背后的底层逻辑与实战价值。
让你不仅知道“要不要上 CRM”,更清楚“该怎么用好 CRM”。

一、CRM不是工具,而是一套以客户为中心的管理体系

1.1 CRM的定义与本质

CRM(Customer Relationship Management),即客户关系管理系统,核心目标并非简单地“记录客户信息”,
而是通过技术手段,构建一套覆盖从获客 → 成交 → 复购/续费的可追踪、可优化、可复制的管理机制。
根据Gartner在《2024年CRM市场指南》中的定义:“现代CRM系统已超越传统销售自动化范畴,演变为集营销获客、销售转化、客户服务与数据分析于一体的智能客户运营平台。”
这意味着,CRM的本质是一种企业级客户资产沉淀机制,而非仅限于前端销售人员使用的辅助工具。

1.2 与Excel、微信标签等“伪CRM”的本质差异

许多企业常误以为“有客户名单就是有CRM”。例如,使用Excel表格管理客户、依赖企业微信打标签、或让销售员在手机备忘录中记录跟进情况。
这些方式虽能短期满足基础需求,但在规模化、流程化、数据驱动层面存在致命短板:
• 信息孤岛严重:客户数据分散在不同员工终端,离职即流失;
• 过程不可见:管理者无法掌握销售推进的真实节奏与卡点;
• 决策无依据:缺乏结构化数据支撑,难以评估渠道效果、销售效能或客户价值。

二、CRM的核心模块:覆盖客户全生命周期(以纷享销客为例)

一个成熟的CRM系统通常包含五大核心功能模块,共同构成客户旅程的完整闭环:

2.1  营销与活动管理

说白了就是帮你把各个渠道来的客户线索“收好、分快、跟准”。
比如你在抖音、百度或者微信投广告,用户一留信息,系统自动抓进来,不漏掉;还能给线索打分,谁更可能成交就优先推给销售。办个线上直播或展会?报名、签到、后续跟进全在线搞定。
最实在的是,花多少钱、带来多少客户、最后成没成交,一笔账清清楚楚,不像以前“钱花了,效果靠猜”。
这样你就能知道哪条渠道真管用,下次把预算花在刀刃上。

2.2  线索管理

帮助企业把从各个地方来的潜在客户(比如官网留言、广告点击、展会名片)统一收进来,不乱不丢。
纷享销客会自动判断谁更可能买——比如有人反复看产品页,就打个高分,优先推给销售;没人跟进的线索还会自动“回收”,转给别人跟。
整个过程像流水线一样:先识别,再打标签,接着分人跟,最后看效果。市场和销售不再扯皮,线索也不再“休冬眠”,转化自然就上去了。

2.3  客户与联系人管理

其实就是帮你把“谁是客户、谁在对接”这件事理得明明白白,不用担心销售离职客户丢失的问题。
比如你公司卖设备给一家工厂,这家工厂就是“客户”,而采购经理老王、技术主管小李就是“联系人”。
系统会把这些信息全记下来——不光是电话微信,还有每次聊了啥、什么时候拜访过、买过什么产品,全都自动归到一起。
哪怕老王跳槽了,新来的销售也能一眼看懂:“哦,原来上次谈的是这个需求,现在该找小李了。”
而且客户还能分级,像A类重点客户,系统会提醒你定期跟进;
要是好久没动静,可能自动放回公海,让别人试试。
这样客户资源就真正变成了公司的资产,不是某个人的私有物。
说白了,就是让客户信息“看得清、跟得上、留得住”。

2.4 商机与销售漏斗管理

商机管理是CRM最核心的价值体现。纷享销客支持企业自定义销售阶段(“初步接洽→需求确认→方案演示→报价谈判→合同签署”),每个阶段设置关键动作与成功标准,形成可视化销售漏斗。
通过漏斗分析,管理者可清晰看到:
• 当前有多少商机处于各阶段?
• 哪个环节流失率最高?
• 下季度预计成交金额是否达标?
更实用的是,系统能自动防撞单、智能预测业绩,并将最佳销售实践固化进流程——新员工照着走就不会跑偏,老员工也能避免凭感觉跟进。最终实现从“靠人盯”到“靠流程驱动”,提升赢单率和预测准确性。

2.5 客户服务管理

纷享销客帮助企业把“售后”这件事做得又快又稳,让客户觉得你靠谱。
比如客户家的设备出问题了,他不用打电话干等,直接扫个码、在微信小程序里点一下,就能提个服务请求。
系统马上收到,自动分给离得最近、有空的工程师——就像打车软件派单一样。
工程师上门前,手机上能看到这台设备以前修过啥、配件用过哪些;
修完还能当场扫码让客户打分,满意不满意一目了然。
要是客户是VIP,系统还会优先安排专属客服,服务更快更贴心。
所有这些流程——从客户报修、派工、上门、用配件、收钱到评价——全在线上走,不靠Excel也不靠嘴记。
老板在后台还能看数据:哪个产品老坏?哪个工程师效率高?客户满意度掉没掉?一清二楚。
总之,就是让服务不乱、不拖、不丢事,客户省心,公司也省力。

2.6  报表与BI分析

BI分析就像给公司装了个“数据仪表盘”,销售做了多少单、客户从哪来、服务满不满意,一眼就能看清。一套好的CRM必须能将过程数据转化为决策洞察。典型报表包括:
• 销售业绩达成率
• 线索来源渠道ROI
• 商机阶段转化率
• 客户生命周期价值(LTV)
更实用的是,它能自动发现谁该复购了——比如客户买的软件快到期了,或者老在用某个功能,系统就会提醒销售!不用靠人脑记,也不用等客户主动找上门。整个过程简单直接:看数据、抓机会、促成交,让老客户不断带来新生意。
说到底,纷享销客CRM做的不是简单的“记客户电话”,而是帮企业把客户当成资产来经营。通过营销自动化 → 智能线索管理 → 标准化销售流程 → 全景客户视图 → 数据驱动服务与复购的完整链路,纷享销客真正实现了:
• 前端:精准获客、高效转化
• 中台:过程可视、协同高效
• 后端:体验保障、价值深耕

三、为什么企业需要CRM?三大角色视角下的真实价值

3.1 对老板:守住客户资产,降低经营风险

对企业主而言,最大的隐性成本不是软件采购费,而是“人走客户飞”。据麦肯锡调研,超过60%的企业客户资源高度依赖个别销售个人关系,一旦核心人员离职,客户流失率高达40%以上。
CRM系统通过强制数据录入与权限管控,确保所有客户互动记录沉淀在系统中。即使销售离职,客户仍属于公司资产,可无缝交接。此外,CRM提供的销售预测与现金流预判功能,让老板告别“拍脑袋定目标”,实现科学经营。

3.2 对销售:减负增效,专注高价值沟通

一线销售最怕“填表式CRM”。真正优秀的系统应成为销售的“智能助手”,而非负担。纷享销客通过以下设计提升销售体验:
• 移动端一键记录:通话后自动生成跟进日志;
• 智能提醒:自动提示“3天未联系的A类客户”;
• 话术库与模板:快速调用成功案例与标准应答;
• 任务自动化:商机推进到下一阶段时,自动创建待办事项。

3.3 对管理者:从“结果管控”转向“过程赋能”

传统管理依赖周报、月报和口头汇报,信息滞后且失真。CRM则实现全流程透明化:
• 可查看每位销售的日程安排、客户拜访轨迹、沟通频次;
• 可对比团队成员在相同阶段的转化效率;
• 可识别高绩效销售的行为模式,并复制推广。
纷享销客的团队协作空间支持跨部门协同(如销售+售前+交付),确保大客户项目高效推进,避免内部扯皮。

四、国产CRM崛起:纷享销客如何满足中国企业的独特需求?

在全球CRM市场,Salesforce长期占据主导地位。但在中国市场,企业对客户资产的精细化运营需求日益迫切——不仅要管好客户信息,更要实现从获客、转化到复购的全生命周期价值挖掘。而国内企业的需求,例如系统集成、审批流程、发票管理,使得国产CRM更具适配性。
纷享销客作为国内领先的智能型CRM厂商,深耕中国市场十余年,产品不仅贴合本土业务逻辑,更积极融合AI能力,打造“智能化+场景化”的新一代客户运营平台。其核心优势体现在以下五个方面:
• 深度集成微信生态:支持企业微信客户同步、聊天侧边栏、朋友圈素材库,实现私域流量无缝管理;
• 灵活审批流:可配置合同审批、折扣申请、回款确认等复杂流程,贴合国内企业内控要求;
• 业财一体化打通:与用友、金蝶等财务系统对接,打通“签约—开票—回款”链条;
• 垂直行业解决方案:针对制造业、医疗、快消、IT服务等垂直领域提供预置模板。
• AI驱动的智能销售助手:系统可以自动分析客户行为、预测成交概率,并在销售跟进中实时推荐话术、成功案例和下一步行动;同时支持自动生成会议纪要、识别商机风险、预警客户流失,帮助销售减少重复工作,专注高价值沟通。更重要的是,纷享销客采用PaaS平台架构,支持企业按需扩展模块(如CPQ报价、服务工单、BI分析),避免“一次性买断但用不起来”的陷阱。这种“用多少、配多少、智能多少”的弹性模式,尤其适合大中型企业。

五、如何选型CRM?七大关键评估维度

当您认识到CRM的价值并准备开始选择时,面对市场上数百款琳琅满目的产品可能会感到无从下手。面对市面上数十款CRM产品,如何为您的企业选择一款合适的CRM系统?建议从以下七个维度综合评估:

结语:CRM不是成本,而是增长基础设施

在数字经济时代,客户关系已成为企业最稀缺的战略资源。CRM系统不再是“可选项”,而是如同ERP、财务系统一样的企业数字基建。
它帮助企业回答三个根本问题:
• 我们到底有多少真实有效的客户?
• 销售团队每天在做什么?效率如何?
• 下个月、下个季度的业绩从哪里来?
总而言之,CRM系统远不止是一个记录客户信息的数据库软件。它是一种将“以客户为中心”的理念融入企业血脉的战略工具,是连接市场、销售和服务,驱动业务流程优化和决策智能化的核心引擎。希望本文能帮助您对CRM有一个清晰的认知。 

常见问题 (FAQ)

1、CRM系统和ERP系统有什么区别?
简单来说,CRM(客户关系管理)主要面向外部,关注的是与客户相关的活动,如市场、销售、服务,目标是增加收入和提升客户满意度。而ERP(企业资源计划)主要面向内部,管理的是企业的核心业务资源,如财务、库存、采购、生产等,目标是优化内部流程和降低成本。两者可以集成,共同构成企业数字化管理的核心。
2、CRM系统一定要全员使用吗?可以只给销售用吗?
A:不建议。CRM的价值在于打通“营销—销售—服务”全链路。若仅销售使用,将导致线索来源不清、售后脱节、数据断层。理想状态是市场、销售、客服、管理层均在系统中有角色和数据贡献。
3、纷享销客和国外CRM(如Salesforce)相比有什么优势?
A:纷享销客在微信生态集成、本地化审批流程、中文界面体验、实施成本及响应速度上更具优势。Salesforce虽功能强大,但对中国企业常见的“人情化流程”“多级审批”“业财一体”支持较弱,且本地化服务成本高。
4、CRM系统主要适用于哪些类型的企业?是不是只有大企业才需要?
答: CRM系统适用于所有有客户并希望与客户建立长期关系的企业,并非大企业专属。不同规模企业需求侧重不同:中小企业可使用CRM标准化销售过程、防止客户流失、提升人效;中大型企业则更侧重于跨部门协同、数据整合分析与生态连接。当前,许多云原生CRM(如纷享销客CRM)提供灵活订阅模式与标准化功能模块,大幅降低了中小企业的使用门槛与启动成本。
5、实施CRM系统最大的挑战是什么?如何规避失败风险?
答: 最大挑战往往来自组织与文化层面,而非技术本身,具体包括:员工抵触改变、使用率低下;业务流程与系统不匹配;数据质量差导致洞察失效。规避风险需:首先,确保高层推动与明确业务目标;其次,选择用户体验好、移动化程度高的系统,降低使用阻力;再次,结合业务痛点梳理优化流程,并进行分阶段上线与持续培训;最后,建立数据治理规范。选择像纷享销客这类重视用户体验与成功服务的厂商,也能获得重要的实施支持。

编者按: 英伟达财报的营收神话是否掩盖了其现金流恶化的现实?而在“循环融资”的质疑声中,OpenAI 与甲骨文等关键客户的供应链“去英伟达化”浪潮,又将如何重塑 AI 硬件的竞争格局?

我们今天为大家带来的这篇文章,作者的观点是:英伟达目前的高速增长依赖于激进的库存策略和宽松的信用条款,但其最大客户正通过定制芯片和直接采购关键组件来构建独立的供应链,这导致双方关系正从深度捆绑走向潜在的激烈竞争。

作者 | Philippe Oger

编译 | 岳扬

过去 48 小时,我完全沉浸在对英伟达 2026 财年第三季度财报[1]的深度研究中。如果你只看新闻标题,一切看起来都完美无缺:营收同比增长 62 %,达到 570 亿美元,黄仁勋还在大谈“AI 的良性循环”。

但我想弄清楚光鲜数据下的真实情况,于是深挖了资产负债表,并将其与围绕 OpenAI 和 Oracle 的所有新闻进行了交叉验证。 我并不是华尔街的专业分析师,但即便仅凭自己梳理线索(并借助了 Gemini 的帮助),我也开始看到这个所谓的“AI 联盟”出现了一些裂痕。就在英伟达创下业绩纪录的同时,他们最大的客户似乎正在悄悄武装自己,准备另起炉灶。

以下是我对硬件市场、OpenAI 与英伟达之间“亦敌亦友”的关系,以及包括迈克尔·贝瑞(Michael Burry)在内大家都在讨论的“循环融资(circular financing)”理论的一些看法。

01 英伟达财报:完美表象下的隐忧

表面看来,英伟达无疑是 AI 时代的绝对王者 —— 数据中心业务已占据公司总营收近九成,这一事实无可辩驳。然而,当我深入研读财报细节时,发现了三处值得警惕的“红色信号”

  • 现金流之谜:英伟达公布的净利润高达 319 亿美元,但我查阅现金流量表时发现,其经营活动产生的现金流仅为 238 亿美元。这意味着有 80 亿美元的利润尚未立即转化为现金。
  • 库存激增:我注意到,今年库存几乎翻倍,达到 198 亿美元。管理层解释称这是为“Blackwell”发布做准备,但在我看来,持有大约 120 天的库存量,会带来巨大的资金占用压力。
  • 应收账款周期拉长:我计算了其应收账款周转天数(DSO),发现已悄然攀升至约 53 天。在营收飙升的同时,英伟达却要等待近两个月才能回款,这暗示他们可能正在向企业客户提供极为宽松的信用条款,以维持增长飞轮的运转。

我的个人判断?英伟达正通过透支现金流来囤积库存,将全部赌注押在 Blackwell 架构[2]能在第四季度被市场瞬间消化。

02 拆解“资金空转”传闻的虚实

我想说清楚一点:接下来这部分内容并不是我最先发现的。最近财经新闻到处都在讨论这件事,而且如果你关注迈克尔·巴里(就是那位电影《大空头》里的“大空头”原型人物),你很可能已经看到他发推文警告所谓的“循环融资”和可疑的收入确认(Revenue Recognition)[3]行为。

我尝试自行理清这其中的关系,看看大家究竟在争论什么。巴里最近分享了一张图表,把这一系列交易描绘成一张交易“关系网”,其结构大致如下:

  • 环节一:英伟达承诺向 OpenAI 投资数十亿美元(这属于已被广泛报道的“千亿美元投资路线图”中的一部分)
  • 环节二:OpenAI 与甲骨文(Oracle)签署了一份高达 3000 亿美元的巨额云服务合同(即“星门计划”,Project Stargate),用于托管其人工智能模型。
  • 环节三:为履行该合约,甲骨文随即向英伟达下达价值 400 亿美元的 GB200 GPU 采购订单。

巴里的核心论点(也是据传美国司法部等监管机构介入调查的原因[4])在于:这套模式形同“资金空转”。这引发了一个尖锐的问题:如果英伟达停止向 OpenAI 投资,OpenAI 还有足够现金去和甲骨文(Oracle)签下那笔大单吗?而甲骨文又是否还会采购那些芯片? 如果答案是“不会”,那么部分营收数据的稳固性可能远不如表面看来那样坚实。

03 OpenAI 正在采取行动降低对英伟达的依赖

我近期一直在关注的另一个重大转变,是 OpenAI 的战略转向。他们曾是英伟达最耀眼的“模范客户”,如今却越来越像一个潜在的竞争对手。一方面,他们仍与 NVIDIA 保持紧密合作 —— 部署 10 吉瓦(gigawatts)的基础设施用于训练 GPT-6;但另一方面,他们似乎正在构建一条能彻底摆脱黄仁勋(Jensen Huang)掌控的供应链。

如果你有所留意,相关迹象其实已经相当明显。 “星门计划”(Project Stargate) 不仅仅是个数据中心,更是一项包含定制硬件在内的庞大基础设施计划。据多家媒体报道(例如此处[5]、此处[6]、此处[7],并在 Hacker News 上引发了激烈的讨论[8]),OpenAI 已直接从三星和 SK 海力士(全球两大 HBM 内存供应商)采购 DRAM 晶圆,绕开了英伟达的供应链。

此外,人才流向也透露出关键信号:OpenAI 已从数个行业巨头处挖走多名芯片人才,包括 2023 年招揽了谷歌前 TPU 负责人 Richard Ho,以及近期从苹果挖走的约 40 名硬件工程师。

结合 OpenAI 与博通(Broadcom)的合作[9],我推测其策略是:用英伟达 GPU 构建智能模型,但最终在自家的定制芯片上运行推理任务 —— 以此大幅削减高昂的运营成本,或押注类似谷歌 Edge TPU 的专用芯片(NPU)来处理推理负载。

但关键问题来了:OpenAI 打算用谁的钱来支持这项事业?而英伟达对其未来规划又究竟有多大影响力?

而且,所谓“英伟达向 OpenAI 投资 1000 亿美元”的说法,至今尚未得到官方证实(如此处[10]所述)。

04 甲骨文一个有趣的思路:收购 Groq

眼下所有人都在讨论推理成本问题(Inference costs) —— 也就是实际运行 ChatGPT 或其他大语言模型(LLM)的花销,远比训练它们更昂贵。我最近在关注 Groq 这家初创公司,他们明确宣称在推理任务上比英伟达更快、更便宜。其创始人乔纳森·罗斯(Jonathan Ross)[11]曾是谷歌 TPU 团队的负责人,甚至可以说是 TPU 概念的最初提出者。

但还有一层情况,我认为被大多数人忽视了:OpenAI 直接采购晶圆所引发的 HBM 短缺问题。

据我所知,目前英伟达最大的瓶颈之一就是 HBM(高带宽内存)。 HBM 由专业内存代工厂生产,而这些产线早已完全超负荷运转。然而,Groq 的架构依赖的是 SRAM(静态随机存储器)。 由于 SRAM 通常是在逻辑制程代工厂(比如台积电 TSMC)中与处理器本身一同制造的,理论上它不会遭遇与 HBM 相同的供应链紧张问题。

综合这些因素,我觉得甲骨文真该认真考虑一下收购 Groq。拿下 Groq 不仅意味着获得更快的芯片,更关键的是 —— 当其他芯片全都售罄时,Groq 的芯片可能仍然有货。这本质上是一种供应链对冲(supply chain hedge)。

对甲骨文的最大客户 OpenAI 而言,这也将带来巨大的优势:更快、更便宜的推理能力。

再结合此前的传闻:甲骨文出租英伟达芯片的利润率极其微薄[12],据传低至 14%,那这笔收购就显得更加合理。通过控股 Groq,甲骨文不仅能摆脱“英伟达税”(NVIDIA Tax),改善自身利润空间,还能彻底绕过 HBM 短缺的困局。

据 Groq 在 2025 年 9 月的最近一轮融资披露[13],其估值约为 69 亿美元。即便支付溢价,以甲骨文的财力也完全有能力完成这笔收购。

但问题是:英伟达会允许这事发生吗?

如果答案是否定的,那又说明了什么?是否意味着当前这套“循环融资(circular financing)”体系中存在某种利益交换 —— 比如,英伟达承诺向 OpenAI 投资 1000 亿美元,条件是甲骨文必须只能使用英伟达芯片?

05 Final Thoughts

进入 2026 年,观察英伟达、OpenAI 与甲骨文之间的博弈,这场三方角力正陷入彼此钳制的僵局。我无从得知英伟达是否事先知晓 OpenAI 与内存厂商之间的晶圆供应协议,亦或其中存在任何合谋?英伟达是否正在极力维持自己在“星门计划”(Stargate)中训练和推理环节的独家地位?而 OpenAI 又到底打算打造什么样的芯片?是类似 TPU/LPU 的架构?还是更偏向 Edge TPU 那样的边缘推理芯片?

迈克尔·巴里(Michael Burry)正在全面做空这套体系[14]。

至于我,只是个读财报的普通人,无力揣测市场走向。但我非常确定一点:AI 硬件市场比以往任何时候都更炽热,未来几个季度的风云变幻必将精彩绝伦。

免责声明:我偶尔会发表些真知灼见,但更多时候说的都是蠢话。阅读本文时请务必谨记这一点。

END

本期互动内容 🍻

❓如果“循环融资”属实,谁最可能成为这个链条中最先断裂的一环?

文中链接

[1]https://nvidianews.nvidia.com/

[2]https://www.nvidia.com/en-us/data-center/technologies/blackwe...

[3]https://www.investing.com/news/stock-market-news/michael-burr...

[4]https://m.economictimes.com/news/international/us/nvidia-reje...

[5]https://openai.com/index/samsung-and-sk-join-stargate/

[6]https://www.asiafinancial.com/samsung-sk-hynix-building-starg...

[7]https://www.kedglobal.com/artificial-intelligence/newsView/ke...

[8]https://news.ycombinator.com/item?id=46169224#46170844

[9]https://openai.com/index/openai-and-broadcom-announce-strateg...

[10]https://fortune.com/2025/12/02/nvidia-openai-deal-not-signed-...

[11]https://www.linkedin.com/in/ross-jonathan/

[12]https://www.fool.com/investing/2025/12/02/michael-burry-just-...

[13]https://groq.com/newsroom/groq-raises-750-million-as-inferenc...

[14]https://www.techradar.com/pro/security/could-the-ai-bubble-be...

本文经原作者授权,由Baihai IDP编译。如需转载译文,请联系获取授权。

原文链接:

https://philippeoger.com/pages/deep-dive-into-nvidias-virtuou...

工作八九年第一次被裁,小孩刚出生,又是年底,心里挺不是滋味的。

项目 2025 年没达到预期,加之公司在推行 ai ,整个项目都裁撤了。

很久没去面试了,不知道开源项目对找工作还有没有帮助。

最近半年维护了一个开源项目,纯前端浏览器生成 PDF,承蒙大家厚爱,收获了一些 star

https://github.com/lmn1919/dompdf.js

体验地址

https://dompdfjs.lisky.com.cn/

欢迎大家去体验,对您有帮助的话也欢迎 star

导读

AI 编码工具正在从"智能补全"演进为能自主完成复杂任务的 Coding Agent。本文基于开源项目源码研究与实践经验,系统性地拆解 Coding Agent 的工作原理。旨在帮助开发者在了解Coding Agent后,与AI伙伴更好的协作配合,更高效的提问和拿到有效结果。

01 背景

AI 编码工具的发展速度快得有点"离谱"。从开始使用 GitHub Copilot 的代码补全,到使用Claude Code、Cursor、Comate IDE等完成复杂编程任务,AI 不再只是个「智能补全工具」,它能读懂你的代码库、执行终端命令、甚至帮你调试问题,成为你的“编码伙伴”。

我自己在团队里推 AI 编码工具的时候,发现一个很有意思的现象:大家都在用,但很少有人真正理解它是怎么工作的。有人觉得它"很神奇",有人吐槽它"经常乱来",还有人担心"会不会把代码搞乱"。这些困惑的背后,其实都指向同一个问题:我们对这个"伙伴"还不够了解。

就像你不会无脑信任一个新来的同事一样,要和 AI 编码伙伴配合好,你得知道它的工作方式、能力边界、以及怎么"沟通"才更有效。

在经过多次的实践尝试后,我尝试探索它的底层原理,并写下了这篇文章记录,主要围绕了这些内容展开:

  • Coding Agent 的核心工作机制,包括身份定义、工具调用、环境感知等基础组成。
  • 从零实现一个最小化 Coding Agent 的完整过程,以建立对 Agent 工作流程的直观理解。
  • 上下文管理、成本控制、冲突管控等生产环境中的关键技术问题及其解决方案。
  • Rule、MCP、Skill 等能力扩展机制的原理与应用场景。

在了解原理后,我和伙伴的协作更佳顺畅,让伙伴更清晰的了解我的意图,我拿到有效的回答。

02 概念

2.1 从Workflow到Agent

取一个实际的例子:休假申请。

如果我们的需求非常简单:

一键申请明天的休假。

在这里插入图片描述

这个需求可以被简化为一个固定的工作流

  1. 打开网页。
  2. 填写起始时间。
  3. 填写结束时间。
  4. 填写休假原因。
  5. 提交表单。

全过程没有任何模糊的输入,使用程序化即可完成,是最原始的工作流形态。

如果需求再模糊一些:

申请后天开始3天休假。

这个需求的特点是没有明确的起始和截止时间,需要从语义上分析出来

  1. 起始时间:后天。
  2. 休假时长:3天。
  3. 转换日期:10.14 - 10.16。
  4. 执行申请:提交表单。

这是一个工作流中使用大模型提取部分参数的典型案例,是模型与工作流的结合。

如果需求更加模糊:

国庆后休假连上下个周末。

这样的需求几乎没有任何直接确定日期的信息,同时由于年份、休假安排等动态因素,大模型不具备直接提取参数的能力。将它进一步分解,需要一个动态决策、逐步分析的过程:

  1. 知道当前年份。
  2. 知道对应年份的国庆休假和调休安排。
  3. 知道国庆后第一天是星期几。
  4. 国庆后第一天到下个周末设为休假日期。
  5. 额外补充调休的日期。
  6. 填写并提交表单。

可以看出来,其中1-5步都是用来最终确定休假日期的,且需要外部信息输入,单独的大模型无法直接完成工作。这是一个典型的Agent流程,通过大模型的智能工具访问外部信息结合实现用户需求。

2.2 什么是Agent

Agent是以大模型为核心,为满足用户的需求,使用一个或多个工具,自动进行多轮模型推理,最终得到结果的工作机制。

2.3 什么是Coding Agent

在Agent的基本定义的基础上,通过提示词、上下文、工具等元素强化“编码”这一目的,所制作的特化的Agent即为Coding Agent。

Coding Agent的最大特征是在工具的选取上,模拟工程师进行代码编写的环境,提供一套完整的编码能力,包括:

  • 阅读和查询代码:

    • 读取文件,对应 cat 命令。
    • 查看目录结构,对应 tree 命令。
    • 通配符查找,对应 ls命令(如 **/*.test.tssrc/components/**/use*.ts)。
    • 正则查找,对应grep 命令(如function print\(.+\) 可以找函数定义)。
    • LSP(Language Server Protocol),用于提供查找定义、查找引用、检查代码错误等能力。
  • 编写或修改代码:

    • 写入文件。
    • 局部编辑文件。
    • 删除文件。
  • 执行或交互命令:

    • 执行终端命令。
    • 查看终端命令stdout输出。
    • 向终端命令stdin 输入内容。

除此之外,通常Coding Agent还具备一些强化效果而设定的工具,通常表现为与Agent自身或外部环境进行交互,例如经常能见到的TODO、MCP、Subagent等等。

03 内部组成

3.1 上下文结构

3.2 身份定义

一个Agent首先会将模型定义成一个具体的身份(红色与橙色部分),例如在社区里常见的这样的说法:

You are a Senior Front-End Developer and an Expert in React, Nexts, JavaScript, TypeScript, HTML, CSS and modern UI/UX frameworks.

在身份的基础上,再附加工作的目标和步骤拆解,比如Cline有类似这样的内容:

https://github.com/cline/cline/blob/4b9dbf11a0816f792f0b3229a08bbb17667f4b73/src/core/prompts/system-prompt/components/objective.ts

  1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
  2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
  3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within <thinking></thinking> tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params). DO NOT ask for more information on optional parameters if it is not provided.
  4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. open index.html to show the website you've built.
  5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.

不用特别仔细地看每一句话,多数Coding Agent会提供一些详实的行动准则、目标要求,这部分称为“Guideline”。

有一些Coding Agent可以在多种模式(或者说智能体)之间进行切换,例如Cursor有Edit、Ask、Plan等,RooCode有Architect、Orchestrator等,有些产品还支持自定义模式。

Cursor

RooCode

选择不同的模式时,实际上会产生不同的目标要求、行为准则,即不同的Guideline环节。因此系统提示词中的身份部分,通常会分成不变的Base Prompt(红色)和可变的Agent Prompt(橙色)两个部分来管理,实际开始任务时再拼装起来。

3.3 工具调用

Agent的另一个最重要的组成部分是工具,没有工具就无法称之为一个Agent。让Agent能够使用工具,就必须要有2部分信息:

  1. 有哪些工具可以用,分别是什么作用。
  2. 如何指定使用一个工具。

对于第一点(哪些工具),在Agent开发过程中,一般视一个工具为一个函数,即由以下几部分组成一个工具的定义:

  1. 名称。
  2. 参数结构。
  3. 输出结构。

实际在调用模型时,“输了结构”往往是不需要提供给模型的,但在Agent的实现上,它依然会被预先定义好。而“名称”和“参数结构”会统一组合成一个结构化的定义,通常所有工具都只接收1个参数(对象类型),用JSON Schema表示参数结构。

一个典型的工具定义:

{
  "name": "read",
  "description": "Read the contents of a file. Optionally specify line range to read only a portion of the file.",
  "parameters": {
    "type": "object",
    "properties": {
      "path": {
        "type": "string",
        "description": "The file path to read from"
      },
      "lineStart": {
        "type": "integer",
        "description": "The starting line number (1-indexed). If not specified, reads from the beginning of the file."
      },
      "lineEnd": {
        "type": "integer",
        "description": "The ending line number (1-indexed). If not specified, reads to the end of the file."
      }
    },
    "required": ["path"]
  }
}

可以简单地把这个工具理解成对应的TypeScript代码:

interface ReadToolParameter {
        path: string;
        lineStart?: number;
        lineEnd?: number;
}

async function read(parameters: ReadToolParameter) {
        // 工具实现
}

对于第2点(指定使用工具),则是要让大模型知道工具调用的具体格式。这在业界通常有2种做法。

第1种以Claud Code、Codex等为典型,使用大模型提供的Function Calling格式调用,分为以下几步:

  1. 在调用大模型时,通过一个tools 字段传递所有的工具定义。
  2. 模型会返回一个消息中包含tool_calls 字段,里面每一个对象是一个工具的调用,使用id 作为唯一标识。
  3. 工具产生的结果,以一条role: 'tool' 的消息返回,其中tool_call_id 与调用的id对应,content 是工具的结果(这里各家模型厂商的实现略有不同,其中Anthropic要求role: user,但content字段中传递toolResult,其结构是[{type: 'tool_result',tool_use_id: toolBlock.id, content: toolResultContent}],tool_use_id与调用的id对应)。

第2种方式是以Cline、RooCode为典型,使用一种自定义的文本格式来表示工具调用,通常选择XML的结构,例如对于Cline,读取一个文件的结构如下:

<read_file>
<path>src/index.ts</path>
</read_file>

只要在模型返回的消息中出现这样的结构,就会被解析为一个工具调用,得到的结果以普通的role: 'user' 的消息返回,包括实际内容和一些提示相关的信息。

Content of src/index.ts:

Note:

- this file is truncated to line 1000, file has a total 2333 lines.
- use read_file with line_start and line_end parameters to read more content.
- use seach_in_files tool searching for specific patterns in this file.

...

3.4 环境感知

Coding Agent之所以可以在一个代码库上执行任务,除了通过工具来遍历、检索代码外,另一个因素是Agent实现会在调用模型时主动地提供一部分与项目有关的信息。

其中对Coding Agent工作最有用的信息之一是代码库的结构,即一个表达出目录、文件结构的树型区块。这部分信息通常会符合以下特征:

  1. 尽可能地保留目录的层级结构,使用换行、缩进的形式表达。
  2. 遵循 .gitignore 等项目配置,被忽略的文件不会表现在树结构中。
  3. 当内容过多时,有一定的裁剪的策略,但同时尽可能多地保留信息。

以Cursor为例,这部分的内容大致如下:

<project_layout>
Below is a snapshot of the current workspace's file structure at the start of the conversation. This snapshot will NOT update during the conversation. It skips over .gitignore patterns.

codex-cursor/
  - AGENTS.md
  - CHANGELOG.md
  - cliff.toml
  - codex-cli/
    - bin/
      - codex.js
      - rg
    - Dockerfile
    - package-lock.json
    - package.json
    - scripts/
      - build_container.sh
      - build_npm_package.py
      - init_firewall.sh
      - [+4 files (1 *.js, 1 *.md, 1 *.py, ...) & 0 dirs]
  - codex-rs/
    - ansi-escape/
      - Cargo.toml
      - README.md
      - src/
        - lib.rs
</project_layout>

当内容数量超过阈值时,会采用广度优先的保留策略(即尽可能地保留上层目录结构),同时对于被隐藏的文件或子目录,会形如 [+4 files (1 *.js, 1 *.md, 1 *.py, ...) & 0 dirs]这样保留一个不同文件后缀的数量信息。

除了目录结构外,还有一系列默认需要模型感知的信息,在一个Coding Agent的工作环境中,它通常分为2大类,各自又有一系列的细项:

  1. 系统信息:

    1. 操作系统(Windows、macOS、Linux,具体版本)。
    2. 命令行语言(Shell、Powershell、ZSH)。
    3. 常见的终端命令是否已经安装( python3nodejqawk等,包含具体版本)。
    4. 代码库目录全路径。
  2. 为Agent扩展能力的信息:

    1. Rule(自动激活的部分)。
    2. Skill(摘要描述部分)。
    3. MCP(需要的Server和Tool列表)。
    4. Memory(通常是全量)。

需要注意的是,环境信息这部分,一般不出现在系统提示词中,而是和用户提问的消息放置在一起。

3.5 简单实现

在身份定义、工具调用、环境感知这3部分最基础的Agent组成都达成后,简单地使用大模型的API,进行自动化的工具调用解析、执行、发送新一轮模型调用,可以非常简单地实现一个最小化的Coding Agent。

可以尝试用以下的提示词,使用任意现有的Coding Agent产品,为你编写一个实现,并自己调试一下,感受Coding Agent的最基础的逻辑:

我希望基于大模型实现一个Coding Agent,以下是我的具体要求:

1. 使用Claude作为模型服务商,使用环境变量管理我的API Key。
2. 默认使用Claude Sonnet 4.5模型。
3. 使用Anthropic's Client SDK调用模型。
4. 不需要支持流式输出。
5. 使用TypeScript编写。

以下是Agent提供的工具:

1. read({path: string}):读取一个文件的内容
2. list({directory: string}):列出一个目录下的一层内容,其中目录以`/`结尾
3. write({path: string, content: string}):向文件写入内容
4. edit({path: string, search: string, replace: string}):提供文件中的一块内容

以下是交互要求:

1. 通过NodeJS CLI调用,支持`query`和`model`两个参数,可以使用`yargs`解析参数。
2. 在System消息中,简短地说明Coding Agent的角色定义、目标和行为准则等。
3. 在第一条User消息中,向模型提供当前的操作系统、Shell语言、当前目录绝对路径信息,同时包含跟随`query`参数的内容,组织成一条模型易于理解的消息。
4. 对每一次模型的工具调用,在控制台打印工具名称和标识性参数,其中标识性参数为`path`或`directory`,根据工具不同来决定。
5. 如果模型未调用工具,则将文本打印到控制台。

请在当前目录下建立一个`package.json`,并开始实现全部的功能。

04 优质上下文工程

4.1 成本控制

大模型是一个非常昂贵的工具,以Claude为例,它的官方API价格如下:

我们可以观察到一些特征:

  1. 输出的价格是输入的5倍(但实际考虑到输出与输出的数量比例,输出的价格根本不值一提)。
  2. 缓存输入(Cache Writes)比正常输入(Base Input)更贵一些,约1.25倍。
  3. 缓存命中(Cache Hits)的价格比正常输入(Base Input)要便宜很多,为1/10的价格。

这就意味着,一个良好使用缓存的Agent实现,其成本会比不用缓存降低8-10倍。因此所有的Coding Agent一定会细致地梳理内容结构,最大化利用缓存

在大模型的API中,缓存通常以“块”为单位控制,例如:

  1. 系统提示词中不变的部分。
  2. 系统提示词中可变部分。
  3. 工具定义。
  4. 每一条消息,单条消息也可以拆成多个块。

继续观察Claude对于缓存控制的文档:

可以看到,在大模型API中各种参数一但有所变动,缓存都会大量失效(至少消息缓存全部失效,大概率系统缓成失效),这就会造成成本的极大提升。因此,在Coding Agent实现中,都会从一开始就确定所有参数,整个任务不做任何变更。一些很经典的实例:

  1. 一次任务不会一部分消息开思考模式,一部分不开,因为思考参数会让全部的消息缓存失效。
  2. 切换不同模式(如Edit、Ask、Plan)时,虽然能使用的工具不同,但只是在消息中增加说明,而不会真的将 tools 字段改变。

另外,Coding Agent会尽可能保持历史消息内容完全不变,以最大化地缓存消息。例如对于一个进行了10轮模型调用的任务,理论上第10次调用中,前9轮的消息内容都会命中缓存。但如果此时擅自去修改了第1轮的工具调用结果(例如试图删除读取的文件内容),看似可能消息的长度减少了,但实际因为缓存被破坏,造成的是10倍的成本提升。

总而言之,缓存是一个至关重要的因素,Coding Agent的策略优化通常以确保缓存有效为前提,仅在非常必要的情况下破坏缓存

4.2 空间管理

Coding Agent因为会自动地与大模型进行多轮的交互,随着不断地读入文件、终端命令输出等信息,上下文的长度会变得非常的大,而大模型通常只具备128K左右的总长度,因此如何将大量内容“适配”到有限的长度中,是一个巨大的挑战。

控制上下文长度的第一种方式是“裁剪”,即在整个上下文中,将没用的信息删除掉。试想如下的场景:

  1. 模型读取了一个文件的内容。
  2. 模型将文件中 foo 这一行改成了 bar
  3. 模型又将文件中 eat 这一行改成了 drink

假设我们对模型每一次修改文件,都返回最新的文件内容,如果这个文件有1000行,那么1次读取、2次修改,就会产生3000行的空间占用

一种优化方式就是,在这种连续的读-改的场景下,只保留最后一条消息中有全文内容,即上述3次模型调用后,出现在上下文中的内容实际是这样的:

<!-- Assistant -->
read(file)

<!-- User -->
[This file has been updated later, outdated contents are purged from here]

<!-- Assistant -->
edit(file, foo -> bar)

<!-- User -->
The edit has been applied successfully.

--- a/file
+++ b/file
@@ -23,1 +23,1 @@
-foo
+bar

[This file has been updated later, outdated contents are purged from here]

<!-- Assistant -->
edit(file, eat -> drink)

<!-- User -->
The edit has been applied successfully, the new file content is as below:

{content of file}

可以看到,通过将连续对同一文件的修改进行裁剪,可以只保留最新的内容,同时又使用unidiff 之类的形式保留中间编辑的差异信息,最大限度地降低空间占用,又能保留模型的推理逻辑。

但裁剪不能使用在非连续的消息中,随意地使用剪裁逻辑,很有可能破坏消息缓存结构,进而使模型调用的输入无法通过缓存处理,几倍地增加模型的调用成本。

即便裁剪有一定效果,但随着更多的内容进入到上下文中,始终会有将上下文占满的时候,此时模型将完全无法进行推理。为了避免这种情况出现,Coding Agent通常会使用“压缩”这一技术,即将前文通过模型摘要成少量的文字,同时又保留比较关键的推理链路。

通常,压缩在上下文即将用完的时候触发,如已经使用了90%的上下文则启动压缩,压缩的目标是将90%的内容变为10%的长度,即省出80%的空间供后续推理。

压缩本身是一个模型的任务,即将所有的上下文(可以选择性地保留最新的1-2对消息)交给模型,同时附带一个压缩的要求,让模型完成工作。这个压缩的要求的质量将决定压缩的最终结果,一个比较典型的实现是Claude Code的“八段式摘要”法:

const COMPRESSION_SECTIONS = [
  "1. Primary Request and Intent",    // 主要请求和意图
  "2. Key Technical Concepts",        // 关键技术概念
  "3. Files and Code Sections",       // 文件和代码段
  "4. Errors and fixes",              // 错误和修复
  "5. Problem Solving",               // 问题解决
  "6. All user messages",             // 所有用户消息
  "7. Pending Tasks",                 // 待处理任务
  "8. Current Work"                   // 当前工作
];

通过将信息压缩成8部分内容,能够最大限度地保留工作目标、进度、待办的内容。

4.3 独立上下文

在实际的应用中,其实大概率是不需要128K上下文用满的,但真实表现又往往是上下文不够用。这中间存在的差异,在于2类情况:

  1. 为了满足一个任务,需要收集大量的信息,但收集到正常信息的过程中,会引入无效的、错误的内容,占用上下文。
  2. 一个任务足够复杂,分解为多个小任务后各自占用部分上下文,但加起来以后会超出限制。

试想一下,对于一个这样的任务:

修改我的Webpack配置,调整文件拆分逻辑,让最终产出的各个JS文件大小尽可能平均。

但是很“不幸”地,这个项目中存在6个 webpack.config.ts文件,且最终splitChunks 配置在一个名为 optimization.ts 的文件中管理,那么对于Coding Agent来说,这个任务中就可能存在大量无意义的上下文占用:

  1. 读取了6个 webpack.config.ts ,一共2000行的配置内容,但没有任何splitChunks 的配置,包含了大量 import 其它模块。
  2. 又读取了10个被 import 的模块,最终找到了 optimization.ts 文件。
  3. 经过修改后,执行了一次 npm run build 来分析产出,发现JS的体积不够平均。
  4. 又修改 optimization.ts ,再次编译,再看产出。
  5. 循环往复了8次,终于在最后一次实现了合理的splitChunks 配置。

这里面的“6个 webpack.config.ts ”、“10个其它模块”、“8次优化和编译”都是对任务最终目标并不有效的内容,如果它们占用150K的上下文,这个任务就不得不在中途进行1-2次的压缩,才能够最终完成。

为了解决这个问题,当前多数的Coding Agent都会有一个称为“Subagent”的概念。就好比一个进程如果只能使用4GB的内存,而要做完一件事需要16GB,最好的办法就是开5个进程。Subagent是一种类似子进程的,在独立的上下文空间中运行,与主任务仅进行必要信息交换的工作机制

再回到上面的案例,在Subagent的加持下,我们可以将它变成以下的过程:

  1. 启动一个Subagent,给定目标“找到Webpack文件拆分的代码”。

    1. 读取6个 webpack.config.ts
    2. 读取10个被 import 的模块。
    3. 确定目标文件 optimization.ts
    4. 返回总结:在 optimization.ts 中有文件拆分的配置,当前配置为……。
  2. 启动一个Subagent,给定目标“修改 optimization.ts ,使产出的JS体积平均,执行 npm run build 并返回不平均的文件“。

    1. 修改 optimization.ts
    2. 执行 npm run build,得到命令输出。
    3. 分析输出,找到特别大的JS文件,返回总结:配置已经修改,当前 xxx.js 体积为平均值的3倍(723KB),其它文件体积正常。
  3. 启动一个Subagent,给宝目标“分析 dist/stats.json,检查 xxx.js 中的模块,修改 optimization.ts 使其分为3个250KB左右的文件,执行 npm run build并返回不平均的文件”。

    1. ……
    2. ……
  4. 继续启动6次Subagent,直到结果满意。

不难看出来,这种模式下主体的Coding Agent实际是在"指挥"Subagent做事,自身的上下文占用是非常有限的。而Subagent仅“专注”于一个小目标,也不需要太多的上下文,最终通过这类不断开辟新上下文空间的方式,将一个复杂的任务完成。

4.4 注意力优化

如果你经常使用Coding Agent,或在业界早期有过比较多的使用经验,你可能会发现这种情况:Coding Agent在完成一个任务到一半时,忘了自己要做什么,草草地结束了任务,或偏离了既定目标产生很多随机的行为。

会发生这样的情况,有一定可能是裁剪、压缩等策略使有效的上下文信息丢失了,但更多是因为简单的一个用户需求被大量的代码内容、命令输出等推理过程所掩盖,权重弱化到已经不被大模型“注意到”,因此最初的目标也就完全丢失了。

Coding Agent一个很重要的任务,就是在长时间运作的同时随时调整大模型的注意力,使其始终聚焦在最终目标、关注当前最需要做的工作,不要偏离预先设定的路线。为了实现这一效果,Coding Agent产品提出了2个常见的概念。

第一称为TODO,在很多的产品中,你会看到Agent先将任务分解成几个步骤,转为一个待办列表。这个列表在界面上始终处于固定的位置,随着任务的推进会逐步标记为完成。这个TODO实际上并不是给用户看的,而是给模型看的

在实际的实现中,每一次调用模型时,在最后一条消息(一般就是工具调用的结果)上,除了原始消息内容外,会增加一个称为“Reminder”的区域。这个区域因为始终出现在所有消息的最后,通常来说在模型的注意力中优先级更高,而且绝对不会受其它因素影响而消失

Reminder中可以放置任意内容,比较经典的有:

  1. TODO及进度。用于模型时刻理解目标、进展、待办。
<reminders>
- Planned todos:
  - [x] Explore for code related to "print" function
  - [x] Add "flush" parameter to function
  - [ ] Refactor all "print" function calls to relect the new parameter
</reminders>
  1. 工具子集。如前面《缓存》相关的描述,因为修改工具定义会使缓存失效,因此当切换模式使得可用的工具减少时,一般仅在Reminder中说明部分工具不可用,由模型来遵循这一约束,而不是直接删除部分工具。
<!-- 切换至Ask模式 -->
<reminders>
- You can ONLY use these tools from now on:
  - read
  - list
  - grep
  - bash
</reminders>
  1. 行为指示。例如当模型连续多次给出名称、参数都一模一样的工具调用时,说明模型处在一种不合理的行为表现上,此时在Reminder中增加提示,让模型感知到当前状态的错误,就有可能调整并脱离错误的路线。
<!-- Assistant -->
read(file)

<!-- User -->
The file content: ...

<!-- Assistant -->
read(file)

<!-- User -->
The file content: ...

<reminders>
- Your are using read tool the second time with exactly the same parameters, this usually means an unexpected situation, you should not use this tool again in your response.
</reminders>
  1. 状态提示。例如激活某一个Skill时,Reminder中可以提示“当前正在使用名为X的Skill“,这种提示可以让模型更加专注于完成一个局部的工作。
<reminders>
- You are currently working with the skill "ppt" active, be focused on this task until you quit with exit_skill tool.
</reminders>

需要额外注意的是,Reminder仅在最后一条消息中出现,当有新的消息时,旧消息上的Reminder会被移除。基于这一特征,我们知道Reminder是永远无法命中缓存的,因此Reminder部分的内容长度要有控制,避免造成过多的成本消耗。

4.5 冲突管控

随着Coding Agent能力的发展,当下执行的任务时间越来越长、编辑的文件越来越多,同时更多的用户也习惯于在Agent工作的同时自己也进行编码工作,甚至让多个Agent任务并发执行。这种“协同”形态下,不少用户曾经遇到过这样的问题:

自己将Agent生成的代码做了一些修正,但之后Agent又把代码改了回去。

这个现象的基本原因也很清楚,就是Agent并不知道你改动过代码。例如以下的过程使Agent读取并编辑了一个文件:

<!-- Assistant -->
read(file)

<!-- User -->
The file content:
...
console.log('hello');
...
<!-- Assistant -->
edit(file, hello -> Hello)

<!-- User -->
Edit has been applied successfully.

这个时候,在模型见到的上下文中,这个文件中的代码显然是console.log('Hello'); 。假设乃又将它改成了console.trace('Hello'); ,后面模型依然会基于.log 来修改代码,用户看起来就是代码“改了回去”。

解决这种共同编辑文件的冲突,实际上有多种方法:

  • 加锁法。当Agent读取、编辑一个文件时,更新模型认知的文件内容的快照。当这个Agent再一次编辑这个文件时,读取文件当前的实际内容,和快照做比对,如果内容不一样,拒绝这一次编辑,随后要求Agent重新读取文件(更新快照与实际内容一致)再进行编辑。这是一种主流的做法,不过Agent实现上的细节比较重
<!-- Assistant -->
edit(file, console.log...)

<!-- User -->
This edit is rejected, the file has been modified since your last read or edit, you should read this file again before executing any write or edit actions.

<!-- Assistant -->
read(file)

<!-- User -->
The file content: ...

<!-- Assistant -->
edit(file, console.trace...);
  • 推送法。监听所有模型读取、编辑过的文件的变更,当文件发生变更时,在下一次模型调用时,不断通过Reminder区域追加这些变更,让模型“实时”地知道文件有所变化,直到文件被下一次读取。这种方式能让模型更早地感知变化,但推送信息可能过多影响成本和推理速度。
<!-- Assistant -->
run_command(ls)

<!-- User -->
The command output: ...

<reminders>
- These files have been modified since your last read or edit, you should read before write or edit to them:
  - file
  - file
  - ...
</reminders>
  • 隔离法。使用Git Worktree方案,直接让不同的Agent任务在文件系统上隔离,在一个独立的Git分支上并行工作,相互不受干扰。在任务完成后,用户检查一个任务的全部变更,在采纳时再合并回实际的当前Git分支,有冲突的由用户解决冲突。这种方法让Agent根本不需要考虑冲突问题,但缺点是系统资源占用高,且有合并冲突风险

文件编辑冲突只是一个比较常见的现象,实际上用户和Agent、多个Agent并行工作,可能造成的冲突还有很多种,例如:

用户敲了半行命令 ls -,Agent直接在终端里敲新的命令 grep "print" -r src执行,导致最后的命令是 ls -grep "print" -r src ,是一个不合法的命令。

终端的抢占也是一种冲突,但相对更容易解决,只要让每一个Agent任务独占自己的终端,永远不与用户、其它Agent任务相交叉即可。

4.6 持久记忆

我们都知道,模型是没有状态的,所以每一次Agent执行任务,对整个项目、对用户的倾向,都是从零开始的过程。这相当于历史经验无法积累,很多曾经调整过的细节、优化过的方向都会被重置。虽然可以通过比如Rule这样的方式去持久化这些“经验”,但需要用户主动的介入,使用成本是相对比较高的。

因此当前很多Coding Agent产品都在探索“记忆”这一能力,争取让Agent变得用的越多越好用。记忆这个话题真正的难点在于:

  1. 如何触发记忆。
  2. 如何消费记忆。
  3. 什么东西算是记忆。

首先对于“如何触发”这一问题,常见于2种做法:

  1. 工具型。定义一个 update_memory 工具,将记忆作为一个字符串数组看待,工具能够对其进行增、删改,模型在任务过程中实时地决定调用。往往模型并不怎么喜欢使用这类工具,经常见于用户有强烈情感的描述时才出现,比如“记住这一点”、“不要再……”。
  2. 总结型。在每一次对话结束后,将对话全部内容发送给模型,并配上提示词进行记忆的提取,提取后的内容补充到原本记忆中。总结型的方案往往又会过度地提取记忆,将没必要的信息进行持久化,干扰未来的推理。
  3. 存储型。不进行任何的记忆整理和提取,而是将所有任务的原始过程当作记忆,只在后续“消费”的环节做精细的处理。

然后在“如何消费”的问题下,也常见有几种做法:

  1. 始终附带。记忆内容记录在文件中,Agent实现中将文件内容附带在每一次的模型请求中。即模型始终能看到所有的记忆,这无疑会加重模型的认知负担,也占用相当多的上下文空间,因为很多记忆可能是与当前任务无关的。
  2. 渐进检索。本身不带记忆内容到模型,但将记忆以文件系统的形式存放,Agent可以通过readlistgrep 等工具来检索记忆。配合“存储型”的触发方式,能让全量的历史任务都成为可被检索的记忆。但这种方式要求模型有比较强的对记忆的认知,在正确的时刻去找相关的记忆。但往往因为根本不知道记忆里有什么,进而无法知道什么时候应该检索,最终几乎不触发检索。

而最终的问题,“什么东西是记忆”,是当下Coding Agent最难以解决的问题之一。错误的、不必要的记忆甚至可能造成实际任务效果的下降,因此精确地定义记忆是Agent实现的首要任务。

通常来说,记忆会分为2种大的方向:

  1. 事实型。如“使用4个空格作为缩进”、“不要使用any 类型“,这些都是事实。事实是无关任何情感、不带主观情绪的。
  2. 画像型。如”用户更喜欢简短的任务总结“就是一种对用户的画像。画像是单个用户的特征,并不一定与项目、代码、架构相关。

在Coding Agent上,往往更倾向于对”事实型“的内容进行记忆,而不考虑用户画像型的记忆。

同时,从业界的发展,可以看到越来越多的模型厂商在从底层进行记忆能力的开发,如最近Google的Titan架构就是一种记忆相关的技术。可能未来某一天,Agent实现上已经不需要再关注记忆的逻辑与实现,模型自身将带有持久化的记忆能力。

05 能力扩展

在实际应用中,还需要一些机制来让Agent更好地适应特定的项目、团队和个人习惯。当前主流的Coding Agent产品都提供了Rule、MCP、Skill这三种扩展能力,它们各有侧重,共同构成了Agent的能力增强体系。

5.1 Rule

当面对业务的repo往往存在一些领域相关的知识而非模型的知识库中已有的内容,这些往往需要凭借老员工的经验或者读取大量代码库的信息进行总结后才能明白,这些内容便适合放到Rule中,作为静态的不会频繁改动的内容放入Environment Context中长期Cache。

好的Rule应当足够精简、可操作且范围明确,人看不懂的规则或者描述不清的规则模型是一定搞不定无法遵守的。

  • 将Rule控制在 500 行以内。
  • 将较大的规则拆分为多个可组合的规则,采取按需的方式,按照 文件路径/关键场景 激活Rule;对于特定场景激活的Rule,采取编写索引的方式创建Rule,让模型渐进式激活,比如项目针对网络请求和错误处理相关做了项目维度的封装处理,但这种情况并不是每个文件ts/tsx文件都会遇到的诉求,比如在项目的rules目录下创建index.mdr(curso是.mdc文件),编写下面的激活的条件:

    • 需要进行API调用获取数据
    • 处理异步操作的错误和加载状态

-   当编码涉及以下任一情况时,必须立刻阅读 \[08-api-error-handling.mdc\](mdr:.cursor/rules/08-api-error-handling.mdc)
    
  • 提供具体示例或参考文件,针对xx情况正确的方式是\`code\`。
  • 避免模糊的指导,比如交互式的东西模型交互不了,不需要写进去。
  • 为了模型能够积极验证每次改动是否符合预期,告知模型改动后可以执行的正确的构建命令,以及某些自定义命令(比如自动化测试)引导模型在后台启动命令,在xx秒后读取日志文件的内容进行结果的判断。

5.2 MCP

MCP(Model Context Protocol)是Anthropic提出的一种标准化的工具扩展协议,它允许开发者以统一的方式为Coding Agent添加新的能力。

与Rule的"声明式约束"不同,MCP是一种实时工具调用协议,即通过MCP server的方式进行连接,来扩展Agent可以做的事情。

一个典型的场景是集成外部服务。比如你的项目托管在GitHub上,可以让Agent直接访问GitHub实现创建Issue、查询PR状态、添加评论等功能:

{
    "mcpServers": {
        "github": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-github"],
            "env": {
                "GITHUB_PERSONAL_ACCESS_TOKEN": "<your-github-token>"
            }
        }
    }
}

配置好后,Agent就能在代码审查过程中自动创建Issue记录问题、查询相关PR的讨论、甚至根据代码变更自动生成commit message。

MCP的另一个优势是实现门槛低。一个MCP Server本质上就是一个标准输入输出的程序,它通过JSON-RPC协议与Agent通信,当模型需要外部能力的时候,调用MCP Server,而模型无需关心其内部代码实现,Agent只需要按照固定的协议去连接获取内容。

5.3 Skill

5.3.1 什么是Skill

随着模型能力的提升,使用Agent完成的任务复杂度逐渐增加,使用Coding Agent可以进行本地代码执行和文件系统完成跨领域的复杂任务。但随着这些Agent的功能越来越强大,我们需要更具可组合性、可扩展性和可移植性的方法,为它们配备特定领域的专业知识,因此Agent Skill作为一种为Agent扩展能力的标准诞生。Skill 将指令、脚本和资源的文件夹打包,形成专业领域的知识,Agent在初始化的时候会获取可用的Skills列表,并在需要的时候动态加载这些内容来执行特定任务。

随着 Skill 复杂性的增加,它们可能包含过多的上下文信息,无法放入单个配置文件中 SKILL.md,或者某些上下文信息仅在特定场景下才相关。在这种情况下,Skill可以在当前目录中bundle额外的文件,并通过文件名引用这些文件,这些额外的文件提供了更多详细信息,Coding Agent 可以根据需要选择浏览和查找这些信息。Skill 是渐进式触发的, 因此 SKILL.mdnamedescription很关键,这会始终存在于Agent的环境上下文中提供给模型,模型会根据这些描述信息来决定是否在当前任务中触发该Skill,当你明确希望使用某个Skill完成任务,可以在prompt中指定“使用xxxx Skill完成xx任务”。

5.3.2 Skill和代码执行

LLM在很多任务上表现出色,但许多操作需要使用编写代码 -> 代码执行的方式,带来更高效的操作、确定性的以及可靠性的结果。生成式的模型常常通过生成可执行代码的方式去验证/计算结果。

代码既可以作为可执行工具,也可以作为文档。Skill中应该明确让模型是应该直接运行脚本,还是应该将其作为参考信息读取到上下文中。

5.3.3 如何创建Skill

每个Skill由一个必需的 SKILL.md 文件和可选的bundle资源组成,Skill 应该只包含完成任务所需的信息。

skill-name/
├── SKILL.md (必需)
│   ├── YAML frontmatter 元数据 (必需)
│   │   ├── name: (必需)
│   │   ├── description: (必需,这是 skill 的主要触发机制,帮助模型理解何时使用该 skil)
│   │   └── compatibility: (可选)
│   └── Markdown 说明 (必需)
└── bundle的资源 (可选)
    ├── scripts/          - 可执行代码 (Python/Bash/等)
    ├── references/       - 需要时加载到上下文的文档
    └── assets/           - 用于输出的文件 (模板、图标、字体等)

举一个具体的例子,比如当我们需要进行批量项目的技术栈migrate,比如将less迁移postcss,中间涉及一系列的复杂步骤,比如:

  • 安装postcss以及postcss plugin的依赖
  • 配置postcss的config
  • 分析项目用到了哪些less varibale替换成css vars
  • 删除mixin并替换
  • 一系列的其他兼容less的语法转换...
  • 替换文件后缀

上面的工作可以通过清晰的流程描述,并配合脚本实现,因此可以作为一个Skill将经验变成可复制的,一个less-to-postcss的skill的结构:

5.3.4 Skill的使用

人人都可以创建Skill,也可以让Agent来编写Skill,这是Skill非常便捷的地方。Skill通过instructions和code赋予Coding Agent新的能力。虽然这使其功能强大并有很高的自由度,但也意味着恶意SKill可能会在其使用环境中引入漏洞,诱使模型窃取数据并执行非预期操作。仅从可信来源安装Skill,如果无法确信来源可信,在使用前请务必进行彻底审核。

Skill的出现并不是替代MCP的出现,而是相互配合,在合适的场景下选取Skill或是MCP。某些任务Skill和MCP Server均可完成,但Skill通过执行代码的方式可以一次性加载完整流程,但MCP Server要经历多次查询和多轮对话往返,这种情况下Skill更为合适,但这不意味着绝对的优势,比如标准化文档创建这个典型的场景,创建PPT/Word/Excel在本地使用Skill即可完成,但数据的提供则需要借助MCP Server进行查询。因此Skill擅长的是在本地通过执行 code的方式完成复杂任务,在用户私有数据、动态数据查询这些情况下Skill就无法搞定了,这和用户的数据库以及隐私强关联,需要让模型无法感知在执行过程中的隐私信息,Skill能够与MCP Server互补完成更为复杂的流程。

在不少后端团队里,都发生过类似的场景:
Redis 上线后,监控显示 API 核心查询耗时下降了 80%,但用户依旧抱怨接口“卡”“慢”“不稳定”。

于是问题开始在群里反复出现:

  • 是 Redis 集群不够大?
  • 是云厂商网络抖动?
  • 是流量高峰超出预期?
    直到真正拆开一次请求的完整生命周期,才会意识到一个事实:Redis 可能已经做到极致了,只是你把它用在了最不应当的位置。

一个被反复误解的事实
必须先说清楚一句话:
Redis 并不能让一个设计本身就臃肿的 API 变快,它只会让问题暴露得更明显。

在微服务架构下,Redis 几乎成了“性能优化”的默认答案。只要接口慢,第一反应往往是:“加一层缓存”。
但在真实生产环境中,API 的执行路径通常远比你想象得复杂。

客户端
  ↓
API 网关
  ↓
鉴权 / 鉴权扩展
  ↓
参数校验 / 特性开关
  ↓
缓存查询
    ↓(未命中)
数据库查询 → 关联查询 → ORM 映射
  ↓
DTO 转换 / 序列化
  ↓
日志 / 监控 / Trace
  ↓
响应返回

在这条链路里,Redis 只是其中极短的一段。如果你把注意力全部放在“Redis 查得够不够快”,那基本已经跑偏了。
Redis 并不是瓶颈,但常常被用来背锅
我们曾协助排查过一个典型系统:
一个对外提供实时报表查询的金融 API,客户团队坚信性能问题出在 Redis。
他们的监控面板显示:

  • API 平均响应时间:380–450 ms
  • 高峰期 P95 甚至逼近 700 ms

但在引入分段 Trace 后,结果令人意外:

  • Redis GET 操作:稳定在 2–4 ms
  • 超过 85% 的耗时,发生在:

    • 鉴权拦截器
    • 参数反序列化
    • ORM 对象构建
    • JSON 序列化与日志写入
      结论很直接:
      缓存很快,API 还是慢。
      这也是许多团队真正“顿悟”的时刻——
      Redis 没有失效,只是你让它介入得太晚了。

为什么“加了 Redis”却几乎没加速?
归纳下来,问题通常集中在三个方面。

  1. 缓存命中发生得太晚
    很多系统在设计时,把缓存当作“数据库前的一层挡板”,而不是请求生命周期的一部分。
    结果是:
  2. 请求已经完成了鉴权、校验、上下文构建
  3. 日志、Trace 组件已经初始化
  4. 各种中间对象已经创建
    此时即便 Redis 命中,绝大部分 CPU 和延迟成本已经付出。
  5. 缓存键设计服务于“数据模型”,而非“访问模式”
    另一个常见错误,是缓存整个领域对象,甚至直接缓存 ORM 实体。
    后果通常是:
  6. 键粒度过粗
  7. 访问模式稍有变化就无法复用
  8. 命中率长期徘徊在 50% 以下
    在这种情况下,Redis 更像是一个昂贵的、不稳定的旁路系统。
  9. 冷启动与高峰期未命中被严重低估
    很多团队只关注“平均命中率”,却忽略了两个危险时刻:
  10. 应用刚启动
  11. 流量突然放大
    在这些时刻,大量并发请求同时穿透缓存,数据库和后端逻辑被瞬间放大执行,抖动也由此产生。

让 Redis 真正“拉开差距”的设计方式
当你接受 Redis 不是万能解药之后,优化路径反而变得清晰了。

第一原则:缓存要尽可能早
如果某个请求的数据已经在缓存中,就不应该再经历完整的业务管道。
理想状态是:

  • 命中缓存
  • 直接返回最终响应
  • 绕过数据库、对象映射、序列化等步骤
    第二原则:缓存的是“可直接返回的结果”
    与其缓存领域对象,不如缓存“已经准备好返回给客户端的内容”。
String key = "user:profile:resp:" + userId;
String cached = redis.get(key);if (cached != null) {return cached;}// 未命中,走完整流程
User user = userRepository.findById(userId);
String responseJson = responseMapper.toJson(user);// 合理 TTL,例如 5 分钟
redis.setex(key, 300, responseJson);return responseJson;

这里 Redis 的角色已经发生变化:
它不再是“数据缓存”,而是响应加速。

第三原则:预热比你想象得重要
在优化后,我们为以下场景引入了缓存预热:

  • 服务启动
  • 核心用户或高频接口
  • 已知的高峰前时间段
    这一步往往可以显著降低首批请求的抖动风险。

数据不会说谎
在重构缓存策略后,性能变化非常直观:

  • API 平均响应时间
    从约 410 ms 降至 70–90 ms
  • 数据库查询量
    下降超过 65%
  • 缓存命中率
    稳定在 90% 以上
    更重要的是:延迟开始变得可预测,而不是偶发性飙升。

值得记住的几条经验

  1. 缓存优化首先是架构问题,而不是参数问题:Redis 再快,也无法拯救臃肿的请求链路。
  2. 一次缓存未命中的代价,远高于多数人的直觉:它带来的不是一次查询,而是一整条后端路径的放大执行。
  3. 不要只盯着 Redis 的指标:真正的瓶颈,往往藏在 Redis 之前或之后。

结语:Redis 从来不是问题
Redis 很少是系统变慢的原因,但它经常成为暴露问题的那面镜子。
如果你的 API 在“加了 Redis 之后”依然迟缓,不妨换个角度思考:
也许不是 Redis 没有加速系统,
而是系统本就不该让 Redis 来兜底。

测量全链路、设计有缓存意识的架构,让 Redis 只做它最擅长的事。
这,才是真正的性能提升来源。