Engine.IO 深入指南:Socket.IO 背后的实时传输引擎,API 全解与传输升级原理
Engine.IO 是 socket.io 仓库中负责双向、低延迟通信的底层传输引擎,它实现了基于传输层(HTTP long-polling / WebSocket / WebTransport)的跨浏览器、跨设备通信,是 Socket.IO 协议之下的基石。本篇以仓库中的 Engine.IO 官方文档 为主体,完整覆盖其服务端/客户端用法、Server 与 Socket 的 API、全部构造选项及设计目标,并结合 packages/engine.io 下的 TypeScript 源码,深入讲解握手校验、心跳机制、传输升级探测流程与 WebTransport 支持等实现细节。读完本文,你可以独立完成一个 Engine.IO 服务端的搭建与配置,并理解连接在不同传输之间切换时消息不丢失的底层机制。
一、Engine.IO 在 Socket.IO 体系中的定位
Engine.IO 是 Socket.IO 的传输层实现:它只负责建立并维持一条可靠的、可升级的双向连接通道,不关心业务消息的语义。用官方文档 FAQ 中的比喻来说——Engine 之于 Socket.IO,如同 Connect 之于 Express:它是构建实时框架不可或缺的底层构件,但构建实际应用时你大概率直接使用 Socket.IO,而不会单独使用 Engine.IO。
这一点可以从仓库结构得到印证:
- 服务端实现位于 packages/engine.io(当前版本 6.6.9,
engines要求 Node.js >= 10.2.0); - 浏览器/Node 客户端位于 packages/engine.io-client,暴露为浏览器全局
eio命名空间,Node 环境通过require('engine.io-client')使用; - 协议编解码位于 packages/engine.io-parser;
- 协议的权威规范文档是 Engine.IO Protocol v4,其中描述了握手、心跳、升级、消息与数据包编码的完整规则。
Engine.IO 的五大特性(摘自官方文档):
- 最大可靠性:即使存在代理、负载均衡器、个人防火墙与杀毒软件,连接也能建立(见后文 Goals 与 Architecture 两节);
- 客户端体积最小化:惰性加载传输实现、不携带冗余传输;
- 可扩展性:对负载均衡器友好;
- 面向未来:传输可插拔,新协议(如 WebTransport)可以平滑加入;
- 100% Node.JS core 风格:不提供 API 糖(上层能力留给 Socket.IO 等项目)。
二、快速上手
2.1 服务端:三种启动方式
Engine.IO 提供三种等价的接入方式,全部来自官方文档并经过 入口文件 源码验证。
方式 A:直接监听端口
const engine = require('engine.io');
const server = engine.listen(80);
server.on('connection', socket => {
socket.send('utf 8 string');
socket.send(Buffer.from([0, 1, 2, 3, 4, 5])); // binary data
});
从源码看,listen() 内部会创建一个专用的 http.Server——对普通 HTTP 请求一律返回 501 Not Implemented(因为该端口只用于 WS 升级与握手),然后调用 attach() 将 Engine.IO 挂载上去并监听指定端口。
方式 B:挂载到已有的 http.Server
这是最常用的方式,让一个普通 HTTP 服务器变为 WebSocket 兼容:
const engine = require('engine.io');
const http = require('http').createServer().listen(3000);
const server = engine.attach(http);
server.on('connection', socket => {
socket.on('message', data => { });
socket.on('close', () => { });
});
attach() 会实例化一个 Server 并调用其 attach 方法。在 Server.attach 的实现中,它做了三件关键的事:
- 通过
_computePath计算拦截路径(默认/engine.io/),并缓存原有request监听器; - 注册新的
request处理器:路径匹配时交给handleRequest,否则回落到原来的监听器; - 若启用了 WebSocket 传输,则注册
upgrade处理器交给handleUpgrade;对不匹配的 upgrade 请求,按destroyUpgrade/destroyUpgradeTimeout选项在超时后销毁连接。
方式 C:手动传递请求(最高灵活性)
当你需要把 Engine.IO 嵌入自己的路由框架(如 Express)时,可以实例化 Server 后手动转发请求:
const engine = require('engine.io');
const server = new engine.Server();
server.on('connection', socket => {
socket.send('hi');
});
// …
httpServer.on('upgrade', (req, socket, head) => {
server.handleUpgrade(req, socket, head);
});
httpServer.on('request', (req, res) => {
server.handleRequest(req, res);
});
handleRequest 与 handleUpgrade 的完整签名见下文 API 一节。
2.2 客户端
浏览器端通过引入客户端脚本后使用全局 eio 命名空间:
<script src="/path/to/engine.io.js"></script>
<script>
const socket = new eio.Socket('ws://localhost/');
socket.on('open', () => {
socket.on('message', data => {});
socket.on('close', () => {});
});
</script>
客户端的完整 API(重连、传输选择、选项等)请参考 engine.io-client 的文档。注意:Engine.IO 服务端本身并不托管客户端文件(FAQ 第二节)——它的定位是被 Socket.IO 这类框架打包引用;如果你用的是 Socket.IO,引入其客户端脚本即可,因为它已经内置了 Engine.IO 客户端。
2.3 模块顶层的等价写法
官方文档列举了四种“实例化并挂载”的等价方式:
const httpServer; // 之前用 node.js api 的 http.createServer() 创建
// 先创建 server,再 attach
const eioServer = require('engine.io').Server();
eioServer.attach(httpServer);
// 或将模块作为函数调用,返回 `Server`
const eioServer = require('engine.io')();
eioServer.attach(httpServer);
// 立即 attach
const eioServer = require('engine.io')(httpServer);
// 带自定义选项
const eioServer = require('engine.io')(httpServer, {
maxHttpBufferSize: 1e3
});
对应地,listen 支持传入选项与回调:
const engine = require('engine.io');
const server = engine.listen(3000, {
pingTimeout: 2000,
pingInterval: 10000
});
server.on('connection', /* ... */);
attach 也接受选项,例如替换 WebSocket 引擎:
const engine = require('engine.io');
const httpServer = require('http').createServer().listen(3000);
const server = engine.attach(httpServer, {
wsEngine: require('eiows').Server // 需要自行安装 eiows 依赖
});
server.on('connection', /* ... */);
三、服务端 API 详解
3.1 顶层导出
require('engine.io') 暴露以下成员(对照 engine.io.ts):
事件(由 Server 实例在缓冲区事件上转发):
flush:某个 socket 的写缓冲区正在被刷新时触发。参数:Socket(被刷新的 socket)、Array(写缓冲区);drain:某个 socket 的写缓冲区排空时触发。参数:Socket。
属性:
protocol(Number):协议修订号,来源于engine.io-parser(当前为 v4 协议);Server:Server 类构造器;Socket:Socket 类构造器;Transport(Function):传输构造器基类;transports(Object):可用传输的映射表;- 源码中另外还导出了
parser(engine.io-parser 的再导出)与uServer(基于 uWebSockets.js 的服务端实现,见 userver.ts)。
3.2 Server:事件
Server 继承自 EventEmitter,核心事件如下:
connection:新连接建立时触发。参数:Socket。initial_headers:连接的首个请求写入响应头之前触发。参数:headers(Object,响应头哈希)、req(http.IncomingMessage)。headers:连接所有请求写入响应头之前触发。参数同上。connection_error:建立连接过程中发生错误时触发。参数是一个错误对象:req(http.IncomingMessage):被丢弃的请求;code(Number):Server.errors中的错误码;message(string):Server.errorMessages中的错误信息;context(Object):错误的额外上下文。
错误码与消息的对应表(与 server.ts 中 Server.errors / Server.errorMessages 完全一致):
| Code | Message |
|---|---|
| 0 | "Transport unknown" |
| 1 | "Session ID unknown" |
| 2 | "Bad handshake method" |
| 3 | "Bad request" |
| 4 | "Forbidden" |
| 5 | "Unsupported protocol version" |
从源码看,这些错误分别在以下位置被抛出(见 verify() 与 handshake()):传输名不在 transports 白名单内(0);sid 参数携带但服务端无此会话(1);握手请求不是 GET(2);Origin 头含非法字符、sid 存在但传输名与会话当前传输不匹配、WebSocket 未经升级直接握手等(3);allowRequest 回调以 success = false 结束(4);客户端携带 EIO=3 而服务端未开启 allowEIO3(5)。发生错误时,HTTP 长轮询请求会得到 JSON 格式的 400/403 响应(abortRequest),WebSocket 升级则收到手写的 HTTP/1.1 400 Bad Request 响应后断开(abortUpgrade)。
3.3 Server:属性与构造函数选项
属性(重要提示:在可扩展部署中,以下属性只反映连接到单个进程的客户端数量):
clients(Object):按 id 索引的已连接客户端哈希表;clientsCount(Number):已连接客户端数量。
constructor 接受一个可选选项对象。下表汇总了全部选项、默认值与源码级说明(默认值来源:BaseServer 构造函数 中的 Object.assign):
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
pingTimeout |
Number | 20000 | 多久(毫秒)内没收到 pong 包就认为连接已断开 |
pingInterval |
Number | 25000 | 每多久(毫秒)发送一个新的 ping 包 |
upgradeTimeout |
Number | 10000 | 未完成的传输升级在多少毫秒后被取消 |
maxHttpBufferSize |
Number | 1e6(1 MB) | 单条消息的字节/字符上限,超过即关闭会话(防 DoS) |
allowRequest |
Function | 无 | 接收握手/升级请求作为第一参数的函数,决定是否放行;需以 fn(err, success) 回调作答,success=false 表示拒绝 |
transports |
Array<String> | ['polling', 'websocket'] |
允许使用的传输列表;从源码看还支持 "webtransport",但默认禁用,需手动加入 |
allowUpgrades |
Boolean | true | 是否允许传输升级 |
perMessageDeflate |
Object|Boolean | false | WebSocket permessage-deflate 扩展参数(遵循 ws 模块接口);设为 true 启用,子项 threshold(Number,默认 1024)表示超过该字节数才压缩 |
httpCompression |
Object|Boolean | { threshold: 1024 } |
polling 传输的 zlib 压缩参数;设为 false 禁用,子项 threshold 同上 |
cookie |
Object|Boolean | false | 握手响应头中携带客户端 sid 的 cookie 配置(可用于 sticky-session);默认不发任何 cookie。源码默认合并 { name: "io", path: "/", httpOnly: true, sameSite: "lax" } |
wsEngine |
Function | ws 的 Server |
使用的 WebSocket 服务端实现,必须遵循 ws 接口;也可安装 eiows(C++ 插件)替代 |
cors |
Object | false | 转发给 cors 模块的选项;默认不允许任何 CORS |
initialPacket |
Object | 无 | 可选的附加数据包,会拼接到 Engine.IO 发出的握手包之后;源码中它在 open 包之后作为 message 包发出(见 onOpen()) |
allowEIO3 |
Boolean | false | 是否兼容 v3 协议的 Engine.IO 客户端(即 Socket.IO v2 客户端) |
源码中 Server 还提供了一个官方文档未详述的 use(fn) 方法(BaseServer.use):从源码结构看,它接受 Express 风格的中间件 (req, res, next),并在 handleRequest / handleUpgrade 之前统一执行——例如可以挂载 helmet 之类的安全中间件。开启 cors 选项时,服务端本身就是通过 this.use(require("cors")(...)) 注入的。
其余方法:
close:关闭所有客户端(逐个调用clients[sid].close(true)并清理 WebSocket 服务器),返回Server以便链式调用;handleRequest(req, res):拦截到 Engine 请求时内部调用。参数:http.IncomingMessage、http.ServerResponse。返回Server;handleUpgrade(req, socket, head):拦截到 Engine WS 升级时内部调用。参数与 httpupgrade事件一致:请求对象、TCP socket(net.Stream)、遗留尾字节(Buffer)。返回Server;attach(httpServer, options):将 Server 实例挂载到http.Server,捕获upgrade请求。附加选项:path(String):要拦截的路径名,默认/engine.io(源码默认拼接尾部斜杠);destroyUpgrade(Boolean):是否销毁未被处理的 upgrade 请求,默认true;destroyUpgradeTimeout(Number):未处理请求被结束的毫秒数,默认1000;
generateId(req):生成 socket id,可覆写以生成自定义 id;默认实现返回 base64id 生成的随机串。handshake()支持异步的 id 生成,失败时会以BAD_REQUEST错误关闭连接。
3.4 Socket:连接表示
Socket 是一个客户端的表示,继承自 EventEmitter。
事件:
close:客户端断开时触发。参数:String(关闭原因)、Object(可选的描述对象);message:客户端发送消息时触发。参数:String或Buffer(Unicode 字符串或二进制 Buffer);error:发生错误时触发。参数:Error;upgrading:客户端开始向更优传输(如 WebSocket)升级时触发。参数:Object(新传输);upgrade:客户端完成升级时触发。参数:Object(新传输);flush:写缓冲区正在刷新时触发。参数:Array(写缓冲区);drain:写缓冲区排空时触发;packet:socket 收到数据包(message、ping等)时触发。参数:type(包类型)、data(类型是 message 时的数据);packetCreate:socket 发送数据包之前触发。参数同上;heartbeat:收到ping或pong包时触发(取决于客户端版本)。
属性:
id(String):唯一标识符;server(Server):父级 Engine 引用;request(http.IncomingMessage):产生该 Socket 的原始请求;upgraded(Boolean):传输是否已经升级;readyState(String):opening | open | closing | closed;transport(Transport):当前传输引用。
源码中 Socket 还额外保留了 protocol(3 或 4,取自请求的 EIO 查询参数)与 remoteAddress(缓存客户端 IP,因为请求对象可能稍后失效)。
方法:
send(data, [options], [callback]):发送消息。除非发送二进制数据(原样发出),否则执行message = toString(arguments[0])。- 参数:
String | Buffer | ArrayBuffer | ArrayBufferView(任何实现了toString()的对象,或二进制数据);Object可选选项;Function可选回调,在消息被传输层刷出时执行; - 选项:
compress(Boolean)是否压缩发送数据,使用 polling 时该选项可能忽略并被强制为true;默认true(源码中options.compress = options.compress !== false,即默认压缩); - 返回
Socket以便链式调用。另有一个等价别名write();
- 参数:
close([discard]):断开客户端。从 close() 实现看:若写缓冲区还有未发出的包,它会等待一次drain事件再真正关闭传输,保证已排队消息不丢失。返回Socket以便链式调用。
3.5 心跳机制:v3 与 v4 的方向差异
pingInterval / pingTimeout 是保证连接健康的核心参数。从 onOpen() 源码可以看到协议版本带来的方向差异:
- v4 协议(
EIO=4):由服务端周期性发送 ping,客户端回 pong。schedulePing()按pingInterval定时发 ping,resetPingTimeout()给pingTimeout毫秒设置看门狗,超时则以"ping timeout"关闭连接; - v3 协议(
EIO=3,需allowEIO3: true):方向相反,由客户端发 ping,服务端回 pong,超时窗口是pingInterval + pingTimeout之和。
收到 ping/pong 时都会触发 heartbeat 事件。测试脚本 test:compat-v3(EIO_CLIENT=3 mocha --exit,见 package.json)正是用 v3 客户端回归验证这条兼容路径。
3.6 传输升级:probe 探测流程
“在连接存活期间更换传输而不丢消息”是 Engine.IO 架构的核心(见第六节)。具体到实现,升级由 _maybeUpgrade() 驱动,流程可以归纳为:
- 服务端(或 WebSocket 直连升级)收到新传输连接后,调用
client._maybeUpgrade(transport),并启动upgradeTimeout定时器——超时未完成则关闭新传输; - 新传输上的第一个数据包若是
ping/probe,服务端回pong/probe,并发出upgrading事件; - 期间每 100ms 检查一次旧的 polling 传输是否可写,若可写就主动发送一个
noop空包,强制提前结束当前 polling 周期,加速客户端收到pong并确认升级(源码注释:“we force a polling cycle to ensure a fast upgrade”); - 收到
upgrade包后:丢弃旧传输(transport.discard())、标记upgraded = true、切换transport引用、发出upgrade事件并flush()写缓冲区;若此时 socket 正处于closing状态,则关闭新传输并以"forced close"结束; - 其他异常分支(传输关闭、错误、socket 关闭)都会清理定时器并关闭新传输。
allowUpgrades: false 时,upgrades() 直接返回空数组,握手响应中的 upgrades 字段为空,客户端就不会发起升级。
3.7 WebTransport:源码中的第三传输
官方 README 的 Transports 一节只列出 polling 与 websocket,但从 transports 注册表 和 server.ts 源码看,当前版本已经内置了 WebTransport(基于 HTTP/3 的 QUIC 传输):
- 传输注册表中
polling.upgradesTo = ["websocket", "webtransport"],即 polling 会话既可升级 WebSocket,也可升级 WebTransport; - 它默认禁用,需要在
transports选项中显式加入"webtransport"(ServerOptions 类型定义 中有明确示例); - 从
onWebTransportSession源码结构看:WebTransport 会话不走verify()与中间件流程——若配置了中间件,会话会被直接关闭(注释引用了上游库的已知限制);首个数据包必须是open包,否则会话被关闭;若携带sid则走升级路径,与 WebSocket 升级路径对称; - 仓库提供了完整的运行示例 examples/webtransport(含证书生成脚本 generate_cert.sh),协议规范中 WebTransport 的握手细节见 v4 协议文档。
仓库中还提供了基于 uWebSockets.js 的替代服务端 uServer(userver.ts),测试脚本 test:uws / test:eiows(见 test/common.js)分别用 uWebSockets.js 与 eiows 作为 WebSocket 引擎跑完整回归,验证了 wsEngine 选项的插拔设计。
四、传输(Transports)
服务端当前实现的传输(对照 lib/transports/):
polling:XHR / JSONP 轮询传输。它是一个“多态构造器”:请求携带j查询参数时返回 JSONP 实例,否则返回 XHR 实例。长轮询会话可升级为websocket或webtransport;websocket:WebSocket 传输,默认通过ws包提供(wsEngine选项可替换为eiows等 C++ 实现);webtransport:HTTP/3 / QUIC 传输,默认禁用,需手动启用(见 3.7 节)。
五、调试 / 日志
Engine.IO 使用 debug 库输出日志(源码中各模块使用 engine、engine:socket、engine:transport 等 scope)。要看到全部调试输出,运行时设置 DEBUG 环境变量包含目标 scope:
DEBUG=engine* node myapp
六、设计目标(Goals):为什么先轮询、再升级
官方文档的 Goals 一节回答了 Engine.IO 的核心设计问题,值得完整理解。
Engine 的首要目标是确保最可靠的实时通信。与旧版 Socket.IO 核心不同,它总是先建立一条 HTTP 长轮询连接,然后再尝试“侧面测试”并升级到更优的传输。
WebSocket 连接有两个根本优势:
- 更好的服务端性能
- A:负载均衡器——长轮询的负载均衡是架构噩梦:请求可能来自用户代理的任意多个打开的 socket,但都必须路由到持有该 Engine 连接的那个进程与机器,这显著影响内存与 CPU 占用;
- B:网络流量——WebSocket 的设计前提是每个消息帧周围包裹尽可能少数据;HTTP 1.1 传输中每个消息帧都被 HTTP 头与 chunked 编码帧包围。用 xhr-polling 发送 "Hello world" 的体积必然大于用 WebSocket 发送;
- C:轻量解析——由 B 可知,使用传统 HTTP 请求时服务端必须做更多网络数据解析工作,因此 WebSocket 的另一个优势是更少的服务端 CPU 消耗。
- 更好的用户体验——上述性能收益最终转化为原始数据传输速度,在部分场景下体现为更好的用户体验:重度实时交互应用(如游戏)获益巨大,而实时聊天、新闻流、时间线类应用的用户体验提升则微乎其微。
但直接建立 WebSocket 连接在实践中被证明存在问题:
- 代理——许多企业代理会屏蔽 WebSocket 流量;
- 个人防火墙与杀毒软件——至少 3 款个人安全软件会拦截 WebSocket 流量;
- 云应用平台——部分托管平台曾跟不上 WebSocket 协议的快速演进,应用最终只能退回长轮询,但“require() 一下就能用”的无缝体验随之消失。
这些问题的解法很多时候依赖客户端软件升级,而经验表明依赖客户端升级来交付业务方案是徒劳的:用户代理分布高度碎片化。对用户而言,一次失败的 WebSocket 连接可能意味着至少 10 秒的等待,这会感知上严重伤害体验。
因此,Engine 把可靠性与用户体验放在第一位,把潜在的边际 UX 提升与更高的服务端性能放在第二位。
七、架构(Architecture):传输热切换如何做到不丢消息
Engine 的核心前提是在运行中切换传输:连接以 xhr-polling 开始,但可以随时切换到 WebSocket。
核心难题是:切换传输时如何不丢消息?
答案在于时序与缓冲:Engine 只在两次轮询周期之间才从 polling 切换到其他传输。由于服务端在无活动时经过一定超时会关闭连接,且 polling 传输实现会在连接之间缓冲消息,这两点共同保证了消息不丢失且性能最优。
这个设计的另一个好处是绕开了 Flash Socket 的几乎全部限制(连接慢、文件体积大等),可以安全地惰性加载而不损害体验。
结合 3.6 节的 _maybeUpgrade 源码,可以确认这条链路:升级窗口内的消息进入 writeBuffer → 旧 polling 传输在周期结束时自然关闭(期间由 noop 空包提前“收口”)→ 新传输接管后 flush() 立即把缓冲消息刷出。
八、常见问题(FAQ)
可以不用 Socket.IO 而单独使用 Engine 吗?
完全可以。虽然构建实时应用的推荐框架是 Socket.IO(它提供多路复用、重连等面向真实世界应用的基础特性),但 Engine 可以独立使用。Engine 之于 Socket.IO,如同 Connect 之于 Express。
服务端会托管客户端吗?
不会。主要原因是 Engine 设计为被框架打包引用:Socket.IO 已经包含了 Engine,因此托管两份客户端没有意义。使用 Socket.IO 时,包含其客户端脚本即可覆盖 Engine 客户端。
可以用其他语言实现 Engine 吗?
可以。engine.io-protocol 规范文档 始终包含最新、最权威的协议描述;仓库内还附有 协议 v3 文档 与配套的浏览器测试套件(v4-test-suite、v3-test-suite),其他语言实现可以按协议规范对照验证。
九、测试与运行
服务端测试使用 engine.io-client 作为对端驱动。先 npm install,然后运行 npm test(会先编译 TypeScript 并做格式检查)。从 package.json 的脚本看,测试矩阵覆盖:
test:default:默认配置(ws 引擎 + v4 客户端);test:compat-v3:EIO_CLIENT=3环境变量下用 v3 客户端回归(验证allowEIO3兼容路径,见 test/common.js);test:eiows:EIO_WS_ENGINE=eiows,用 C++ 实现的 eiows 替换 ws;test:uws:EIO_WS_ENGINE=uws,整体基于 uWebSockets.js 的uServer运行。
测试文件位于 packages/engine.io/test/,涵盖连接、二进制、重连、WebSocket 升级、中间件与 WebTransport(webtransport.mjs)等场景。
十、小结
Engine.IO 用一个简洁的 API 表面(listen / attach / Server / Socket)承载了实时通信中最棘手的三个问题:兼容性(先轮询后升级,规避代理、防火墙与平台限制)、可靠性(轮询缓冲 + 周期间切换 + drain 后关闭,保证不丢消息)与可扩展性(wsEngine / transports / allowRequest / 中间件等可插拔点)。它的默认选项(pingInterval: 25000、pingTimeout: 20000、maxHttpBufferSize: 1e6、httpCompression 阈值 1024 字节)为大多数场景提供了安全的起点;而 transports、cookie(sticky-session)、cors、initialPacket 等选项则为生产部署预留了调整空间。理解了本文覆盖的 API 与升级原理之后,再阅读上层 Socket.IO 协议 与 packages/socket.io 的实现会顺畅得多——因为多路复用、命名空间、中间件这些能力,全部构建在这条可靠的双向通道之上。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00