PowerToys Find My Mouse 实现解析:从 Raw Input 状态机到 Windows.UI.Composition 聚光灯渲染
Find My Mouse 是 PowerToys 鼠标工具集(Mouse Utilities)中用于“找回鼠标指针”的工具:通过双击 Ctrl、晃动鼠标或自定义快捷键触发后,在指针位置渲染一个“聚光灯”效果,帮助用户在多显示器环境下快速定位光标。本文基于仓库中的模块文档与 src/modules/MouseUtils/FindMyMouse/ 源码,完整讲解该工具的启用流程、窗口与 Composition 视觉树结构、三种激活方式的状态机与摇动检测算法、聚光灯渲染细节、全部配置项及默认值,以及调试与 UI 自动化测试的验证方式。
1. 功能定位与模块组织
模块文档 doc/devdocs/modules/mouseutils/findmymouse.md 开篇即说明:Find My Mouse 基于 Raymond Chen 的 SuperSonar 工具改造而来,其核心是在激活时于光标位置显示聚光灯效果。模块父级文档 doc/devdocs/modules/mouseutils/readme.md 给出了 Mouse Utilities 的整体架构:Find My Mouse、Mouse Highlighter、Mouse Pointer Crosshairs 均作为独立线程运行在 PowerToys Runner 进程内,只有 Mouse Jump 是独立进程。
这一结论可以从 Runner 的模块加载列表中印证:Runner 启动时加载一组已知模块 DLL,其中包含 PowerToys.FindMyMouse.dll,见 src/runner/main.cpp 中的 knownModules 向量。因此 Find My Mouse 并不以独立进程存在,而是一个被 Runner 动态加载的 PowerToy 模块。
实现核心集中在 src/modules/MouseUtils/FindMyMouse/ 目录:
- FindMyMouse.cpp:主实现(约 1100 行,文件头注释标明 “Based on Raymond Chen's SuperSonar.cpp”);
- FindMyMouse.h:激活方式枚举、默认常量与
FindMyMouseSettings结构体; - WinHookEventIDs.cpp:注册自定义窗口消息
WM_PRIV_SHORTCUT; - trace.cpp:ETW 遥测(如
EnableFindMyMouse、MousePointerFocused)。
2. 类结构:CRTP 基类 SuperSonar + 渲染子类 CompositionSpotlight
文档指出关键函数 s_WndProc 负责处理窗口消息。源码中这一职责由模板类 SuperSonar<D>(CRTP 模式)承担,见 FindMyMouse.cpp:
template<typename D>
struct SuperSonar
{
bool Initialize(HINSTANCE hinst);
void Terminate();
protected:
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
return BaseWndProc(message, wParam, lParam);
}
void BeforeMoveSonar() {}
void AfterMoveSonar() {}
void SetSonarVisibility(bool visible) = delete; // 由派生类实现
void UpdateMouseSnooping();
bool IsForegroundAppExcluded();
// ...
static LRESULT CALLBACK s_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void OnSonarInput(WPARAM flags, HRAWINPUT hInput);
void OnSonarKeyboardInput(RAWINPUT const& input);
void OnSonarMouseInput(RAWINPUT const& input);
void DetectShake();
void StartSonar(FindMyMouseActivationMethod activationMethod);
void StopSonar();
};
设计要点:
- 基类持有全部“逻辑”(窗口创建、Raw Input 解析、双击状态机、摇动检测、启停控制),并通过
Shim()回调派生类的钩子方法; - 派生类
CompositionSpotlight(FindMyMouse.cpp)只负责“呈现”:创建 XAML Island 与 Composition 视觉树、实现SetSonarVisibility的淡入淡出; s_WndProc在WM_NCCREATE时通过lpCreateParams把SuperSonar*存入GWLP_USERDATA,之后每条消息都转发到Shim()->WndProc(),即文档中提到的消息入口。
BaseWndProc(FindMyMouse.cpp)处理的消息集恰好对应文档“Event Handling”一节:
| 消息 | 处理 |
|---|---|
WM_CREATE |
调用 OnSonarCreate()(注册键盘 Raw Input sink)并 UpdateMouseSnooping() |
WM_DESTROY |
调用 OnSonarDestroy(),内部 PostQuitMessage(0) 让消息循环优雅退出 |
WM_INPUT |
分派到 OnSonarKeyboardInput / OnSonarMouseInput |
WM_TIMER(TIMER_ID_TRACK) |
调用 OnMouseTimer() 追踪指针移动/静止 |
WM_NCHITTEST |
返回 HTTRANSPARENT,保证覆盖窗口完全不拦截鼠标 |
WM_PRIV_SHORTCUT |
聚光灯未运行时 StartSonar(Shortcut),运行时则 StopSonar()(即“再按一次取消”) |
3. 启用流程:后台线程 + 消息循环
文档 “Enabling Process” 描述的 enable()(创建后台线程运行 FindMyMouseMain)与 CompositionSpotlight 初始化,对应 FindMyMouse.cpp 的模块入口:
// Based on SuperSonar's original wWinMain.
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
{
if (m_sonar != nullptr)
{
Logger::error("A sonar instance was still working when trying to start a new one.");
return 0;
}
CompositionSpotlight sonar;
sonar.ApplySettings(settings, false); // 文档中的 sonar.ApplySettings(settings, false)
if (!sonar.Initialize(hinst))
{
Logger::error("Couldn't initialize a sonar instance.");
return 0;
}
m_sonar = &sonar;
InitializeWinhookEventIds();
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
m_sonar = nullptr;
return (int)msg.wParam;
}
可以归纳出启用链路与文档一致:
- 模块
enable()置位m_enabled、打点Trace::EnableFindMyMouse(true),并std::thread([=]() { FindMyMouseMain(m_hModule, m_findMyMouseSettings); }).detach()在后台线程运行; FindMyMouseMain先用ApplySettings(settings, false)把配置写入实例字段(此时尚无运行时 Composition 对象,故第二个参数为false);Initialize()注册窗口类并创建两个窗口:一个不可见的staticowner 窗口,和真正的覆盖窗口。
Initialize()(FindMyMouse.cpp)中值得注意的细节:
- 线程被设置为
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,保证多显示器不同 DPI 下坐标换算正确; - 覆盖窗口样式为
WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW,窗口标题固定为PowerToys Find My Mouse; - 窗口类名
FindMyMouse通过GetClassInfoW判重,避免重复注册。
窗口销毁走 Terminate()(FindMyMouse.cpp):由于 Composition/XAML 资源绑定在该线程的 DispatcherQueue 上,销毁动作必须 TryEnqueue 回原线程执行 DestroyWindow(m_hwndOwner),随后 WM_DESTROY → OnSonarDestroy → PostQuitMessage 结束消息循环。这正是文档所说“收到 WM_DESTROY 时 sonar 实例被正确清理、消息循环优雅终止”的完整闭环。
模块对外 API 也很精简(FindMyMouse.h):FindMyMouseMain / FindMyMouseDisable / FindMyMouseIsEnabled / FindMyMouseApplySettings / GetSonarHwnd。其中 FindMyMouseApplySettings 在实例存在时以 applyToRuntimeObjects=true 调用,热更新配置;GetSonarHwnd 供快捷键系统投递自定义消息使用。
4. 激活机制一:双击 Ctrl 的 Raw Input 状态机
文档 “Activation Process” 第 1 步提到“全局低级键盘钩子监听双击 Ctrl”。实现上更精确地说:键盘事件通过 Raw Input(WM_INPUT + RIDEV_INPUTSINK)获得,这是文档 “listens for raw input events using WM_INPUT, which provides more precise and responsive input detection” 的落点。
OnSonarCreate()(FindMyMouse.cpp)在窗口创建时注册键盘 Raw Input 设备:
RAWINPUTDEVICE keyboard{};
keyboard.usUsagePage = HID_USAGE_PAGE_GENERIC;
keyboard.usUsage = HID_USAGE_GENERIC_KEYBOARD;
keyboard.dwFlags = RIDEV_INPUTSINK; // 即使本窗口非前台也能收到消息
keyboard.hwndTarget = m_hwnd;
return RegisterRawInputDevices(&keyboard, 1, sizeof(keyboard));
双击判定不是简单的“两次 keydown”,而是一台五状态机(FindMyMouse.cpp):
enum class SonarState
{
Idle, ControlDown1, ControlUp1, ControlDown2, ControlUp2,
};
核心判定逻辑在 OnSonarKeyboardInput()(FindMyMouse.cpp),规则逐条可验证:
- 只处理
VK_CONTROL且按键物理位置与激活方式匹配:DoubleLeftControlKey要求RI_KEY_E0标志为 0(左 Ctrl),DoubleRightControlKey则相反; - 两次按下之间的间隔必须满足
doubleClickInterval >= min(MIN_DOUBLE_CLICK_TIME, doubleClickTimeSetting / 5)且<= doubleClickTimeSetting(系统双击时间设置),其中MIN_DOUBLE_CLICK_TIME = 100ms是硬下限,注释说明是为了“避免某些键盘发送快速连击”; - 两次按下之间光标位置必须保持不变(
IsEqual(m_lastKeyPos, ptCursor)),否则重置状态机并从当前时刻重新计时; - 若
includeWinKey为 true,则要求左/右 Win 键同时处于按下状态(KeyboardInputCanActivate()通过GetAsyncKeyState(VK_LWIN/VK_RWIN)检查); - 一旦进入
ControlUp2状态,再次按下 Ctrl 会直接StopSonar()——即动画进行中按一次 Ctrl 也能取消。
此外,Shortcut 激活方式下收到按键释放(RI_KEY_BREAK)不会关闭已触发的聚光灯,这是为了避免“松开快捷键”误伤效果。
5. 激活机制二:鼠标摇动(Shake)检测算法
FindMyMouseActivationMethod 枚举(FindMyMouse.h)定义了 4 种方式,Shortcut = 3 为自定义快捷键,默认值为 DoubleLeftControlKey:
enum struct FindMyMouseActivationMethod : int
{
DoubleLeftControlKey = 0,
DoubleRightControlKey = 1,
ShakeMouse = 2,
Shortcut = 3,
EnumElements = 4,
};
摇动检测是源码中算法密度最高的部分。OnSonarMouseInput()(FindMyMouse.cpp)在摇动模式下维护一段“移动历史” m_movementHistory:
- 只记录方向变化的移动段:若与上一段方向(
GetSign(diff.x)、GetSign(diff.y))相同,则合并到上一段,压缩高频消息; - 兼容绝对坐标输入(
MOUSE_MOVE_ABSOLUTE,常见于虚拟机 / RDP 会话),通过相邻绝对坐标差分还原相对位移; - 方向改变时调用
DetectShake()。
DetectShake()(FindMyMouse.cpp)的算法注释写得很直白:“Has distance travelled been much greater than the diagonal of the rectangle containing the movement?” 具体为:
- 先剔除超过
m_shakeIntervalMs(默认 1000ms)的历史移动段; - 累加路径总长
distanceTravelled(各段长度按勾股定理求和),并记录轨迹包围盒的 min/max 坐标; - 若
distanceTravelled < m_shakeMinimumDistance(默认 1000px)直接返回; - 计算包围盒对角线
diagonal,当distanceTravelled / diagonal > m_shakeFactor / 100(默认 400%,即路径长超过对角线 4 倍)时判定为摇动,清空历史并StartSonar()。
这套“路径长/包围盒对角线”比值法天然过滤了直线、缓弧等低曲率移动,而左右快速晃动会使比值迅速拉高。
鼠标侧 Raw Input 采用按需订阅策略:UpdateMouseSnooping()(FindMyMouse.cpp)在“聚光灯运行中 / 状态机非 Idle / 摇动模式”三者之一成立时才注册鼠标 Raw Input sink(RIDEV_INPUTSINK),否则以 RIDEV_REMOVE 注销,从而在不使用时零开销。
6. 激活机制三:自定义快捷键与 WM_PRIV_SHORTCUT
当激活方式选择“自定义快捷键”时,Runner 侧的全局快捷键钩子(即文档中 OnHotkeyEx() 所在位置)把事件转换为一条注册过的私有窗口消息,见 WinHookEventIDs.cpp:
void InitializeWinhookEventIds()
{
std::call_once(init_flag, [&] {
WM_PRIV_SHORTCUT = RegisterWindowMessage(L"{1365FFC7-A44E-4171-9692-A3EEF378AE60}");
});
}
消息 ID 用 RegisterWindowMessage 加 GUID 命名空间,避免与其他模块冲突;快捷键处理端只需 PostMessageW(GetSonarHwnd(), WM_PRIV_SHORTCUT, ...)(文档 “Activation Process” 第 1 步引用的正是这段代码)。BaseWndProc 收到该消息后的 toggle 逻辑与文档引用一致(FindMyMouse.cpp):未运行时 StartSonar(Shortcut),运行中 StopSonar()。
三条激活路径最终都汇聚到 StartSonar()(FindMyMouse.cpp),它首先做两道拦截:
- 若
doNotActivateOnGameMode为 true 且detect_game_mode()检测到 Windows 游戏模式,则放弃激活(默认开启); - 若当前前台进程命中排除列表(
IsForegroundAppExcluded()通过get_process_path+check_excluded_app按路径做大小写不敏感匹配),则放弃激活。
通过拦截后,窗口被 SetWindowPos 到 HWND_TOPMOST 并覆盖整个虚拟屏幕(SM_XVIRTUALSCREEN 等)。源码中有一处带注释的 HACK:窗口位置偏移 1 像素、尺寸缩小 2 像素——“否则当透明窗口铺满整屏时 Windows 会让任务栏透明效果出现闪烁”,这是覆盖全屏透明窗口与 DWM 合成交互的经验细节。
7. 聚光灯渲染:XAML Island + Composition 视觉树
文档 “Sonar Animation” 一句带过的“highlight (ripple/pulse)”实际由 CompositionSpotlight 用 Windows.UI.Composition 完成。OnCompositionCreate()(FindMyMouse.cpp)按注释构建如下结构:
[window hwnd] —— DesktopWindowXamlSource (XAML Island)
\ Grid (透明背景,Stretch)
\ ElementCompositionPreview 手插 Visual:
[root] ContainerVisual (fills host, 初始 Opacity=0, 绑定隐式 Opacity 动画)
\ LayerVisual
\ [spotlight 圆形 ShapeVisual(位于背板之下,透过“洞”可见)]
\ [backdrop:MaskBrush = 暗色源 + 径向渐变遮罩(中心透明、外圈不透明)]
渲染要点:
- 聚光灯不是直接画圆,而是全屏暗色背板被一个“中心透明、边缘不透明”的径向渐变 Mask 遮罩出圆形透光区;透光区下方放置与
spotlightColor一致的椭圆ShapeVisual; - 柔边宽度是固定的像素值:半径 < 300 时为 1px,≥ 300 时为 2px(
featherPixels),并换算成渐变 stop 的Offset; - 缩放动画:触发瞬间聚光灯以
spotlightInitialZoom(默认 9 倍)半径出现,随后半径随 root Opacity 从 0→1 线性收缩到最终半径,由表达式动画Lerp(Vector2(start), Vector2(end), Root.Opacity)驱动(SetupRadiusAnimations,FindMyMouse.cpp),形成“由大变小聚拢”的视觉冲击;柔边 stop 的 Offset 也用表达式动画保持固定像素柔边; - 跟随指针:
AfterMoveSonar()(FindMyMouse.cpp)把渐变EllipseCenter和圆形视觉的Offset更新到光标位置(除以RasterizationScale()换算 DIP); - 淡出与隐藏:
SetSonarVisibility(false)时把 root Opacity 动画目标设为 0,动画完成回调WM_OPACITY_ANIMATION_COMPLETED后,若 Opacity < 0.01 则ShowWindow(SW_HIDE)。若系统关闭了动画效果(GetAnimationsEnabled()为假),时长直接取 1ms,保证效果可即时显隐。
自动关闭逻辑在 OnMouseTimer()(FindMyMouse.cpp):聚光灯出现后等待第一次鼠标移动(SonarWaitingForMouseMove),之后每次移动重置 1000ms 的 TIMER_ID_TRACK 计时器;指针静止满 1 秒即 StopSonar()。按下任意鼠标按键也会立即 StopSonar()(见 OnSonarMouseInput 中 usButtonFlags 分支)——这两点与 UI 测试用例的断言完全对应,见下文。
8. 配置项与默认值全表
FindMyMouseSettings(FindMyMouse.h)汇总了全部配置,默认常量在同文件顶部。结合设置 UI 侧 MouseUtilsViewModel.cs(属性读写 FindMyMouseSettingsConfig.Properties.* 并通知模块)与设置页 MouseUtilsPage.xaml,各配置项如下:
| 设置项 | 结构体字段 | 默认值 | 说明 |
|---|---|---|---|
| 激活方式 | activationMethod |
DoubleLeftControlKey(0) |
0=双击左 Ctrl,1=双击右 Ctrl,2=摇动鼠标,3=自定义快捷键(取值 ≥4 时 UI 侧回退为 0) |
| 需同时按住 Win 键 | includeWinKey |
false |
为 true 时双击 Ctrl 须配合 Win 键按下 |
| 游戏模式不激活 | doNotActivateOnGameMode |
true |
StartSonar 中 detect_game_mode() 拦截 |
| 背板颜色 | backgroundColor |
ARGB 128,0,0,0(50% 黑) |
颜色透明度直接编码在 Alpha 通道(注释说明旧的 overlay_opacity 已并入 A 通道) |
| 聚光灯颜色 | spotlightColor |
ARGB 128,255,255,255(50% 白) |
UI 侧缺省回退 #80FFFFFF |
| 聚光灯半径 | spotlightRadius |
100 | DIP 单位;≥300 时柔边加宽到 2px |
| 动画时长 | animationDurationMs |
500 ms | 淡入时长;≤0 时取 1ms 兜底 |
| 初始缩放 | spotlightInitialZoom |
9 | 出现瞬间半径 = 半径 × 9 后收缩 |
| 摇动最小距离 | shakeMinimumDistance |
1000 px | 路径总长低于该值不判定摇动 |
| 摇动时间窗口 | shakeIntervalMs |
1000 ms | 只统计该窗口内的移动段 |
| 摇动因子 | shakeFactor |
400(%) | 路径长/包围盒对角线须超过 400% |
| 排除应用 | excludedApps |
空 | 前台进程路径命中则不激活 |
| 自定义快捷键 | ActivationShortcut(UI 层) |
DefaultActivationShortcut |
仅在激活方式为 Shortcut 时生效 |
ApplySettings(FindMyMouse.cpp)有两条路径:applyToRuntimeObjects=false 在初始化时直接写字段;true 则通过 DispatcherQueueController 的 TryEnqueue 切回 UI 线程,先停掉半径/柔边表达式动画,再更新颜色、尺寸、EllipseCenter 并重新 SetupRadiusAnimations——这保证运行中修改设置即时生效且线程安全。注意 m_destroyed 标志防止队列回调落到已销毁的实例上。
另外,ViewModel 中 GPOWrapper.GetConfiguredFindMyMouseEnabledValue() 表明该工具的启用状态还可被组策略覆盖(对应仓库 doc/gpo 描述的 GPO 能力)。
9. 事件处理与生命周期小结
把文档 “Event Handling” 一节与源码对齐后,完整的事件矩阵为:
| 事件 | 行为 |
|---|---|
| 键盘:匹配激活键的双击模式 | 状态机推进,满足条件 StartSonar |
| 键盘:其他按键(非 Ctrl 释放) | StopSonar() |
| 键盘:摇动模式下方向变化 | 合并/追加移动历史,DetectShake() |
鼠标:任意按键(usButtonFlags 非 0) |
立即 StopSonar() |
| 鼠标:移动 | 摇动检测 + OnMouseTimer() 重置 1s 静止计时 |
WM_PRIV_SHORTCUT |
toggle:未运行则启动,运行中则取消 |
静止满 1s / 桌面切换(GetCursorPos 失败) |
StopSonar() |
WM_DESTROY(禁用/关闭) |
PostQuitMessage 退出消息循环,m_sonar = nullptr |
10. 调试与 UI 自动化验证
文档 “Debugging” 一节的实践建议(附加到 PowerToys Runner 进程、在 FindMyMouse.cpp 打断点、调试开销可能导致视觉效果卡顿)与“Runner 内线程”的架构结论一致——由于 Find My Mouse 不是独立进程,调试入口只能是 Runner。
仓库中的 UI 自动化测试 FindMyMouseTests.cs 对关键行为做了回归验证,可作为行为事实的补充证据:
TestEnableFindMyMouse:在设置页开启 Find My Mouse、选择 “Press Left Control twice” 并写入外观参数后,按左 Ctrl 两次断言聚光灯出现;再按任意键(SendKeys(Key.A))断言消失;再触发一次后执行鼠标左键点击断言消失——与源码中“其他按键取消 / 鼠标按键取消 / 1s 静止取消”三条退出路径一一对应;TestFindMyMouseDifferentSettings:以自定义背板色(FF0000)与聚光灯色(0000FF)重复验证设置生效路径。
测试参数类 FindMyMouseSettings.cs 中 OverlayOpacity 等字段也印证了旧版 UI 的“透明度 + RGB”拆分已被源码注释所述的“透明度并入颜色 Alpha 通道”新模型取代。
11. 参考文件索引
| 内容 | 路径 |
|---|---|
| 模块开发文档(本文主体) | doc/devdocs/modules/mouseutils/findmymouse.md |
| Mouse Utilities 模块总览 | doc/devdocs/modules/mouseutils/readme.md |
| 主实现(SuperSonar + CompositionSpotlight) | src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp |
| 激活枚举 / 默认值 / 设置结构体 | src/modules/MouseUtils/FindMyMouse/FindMyMouse.h |
| 私有消息 WM_PRIV_SHORTCUT 注册 | src/modules/MouseUtils/FindMyMouse/WinHookEventIDs.cpp |
| Runner 模块加载列表 | src/runner/main.cpp |
| 设置视图模型 | src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs |
| 设置页 UI | src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml |
| UI 自动化测试 | src/modules/MouseUtils/MouseUtils.UITests/FindMyMouseTests.cs |
综合来看,Find My Mouse 是“SuperSonar 逻辑内核 + WinAppSDK Composition 渲染层”的组合:Raw Input 提供低延迟且不被前台窗口抢占的输入通道,五状态机与“路径长/对角线”比值算法分别可靠地识别双击与摇动,而径向渐变 Mask + 表达式动画则用纯合成器路径实现了 9 倍缩放聚拢、半径收缩与淡入淡出的聚光灯效果,全程不依赖 GDI 位图绘制。
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 StartedRust0627
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