Langflow 前端 E2E 测试实践:Playwright 配置、自定义 Fixtures 与 data-testid 选择器体系
Langflow 的前端 E2E 测试体系基于 Playwright 构建,核心是一套"自动错误感知"的自定义 fixture、以 data-testid 为主的选择器目录,以及覆盖画布操作、Playground 会话、模板流程等完整用户路径的 spec 组织方式。本文以仓库中的 E2E 测试技能文档 SKILL.md 为骨架,结合 playwright.config.ts、fixtures.ts 等源码逐一展开,读完你可以掌握:如何运行、过滤和调试 Langflow 的 E2E 测试,如何编写符合规范的 spec(标签、fixture 导入、选择器策略),以及底层响应监控、错误契约、teardown 清理的实现原理。
一、适用范围与技术栈
这套技能文档明确划定了 E2E 测试的适用边界(引自 SKILL.md 的 "When to Apply" 一节):
- 为功能或流程编写 E2E 测试时适用;
- 修复失败的 E2E 测试时适用;
- 评审 E2E 测试覆盖度时适用;
- 修改组件中的
data-testid属性时适用(可能破坏既有测试); - 修改
src/frontend/tests/utils/下的测试工具时适用。
不适用的场景:单元测试(Jest,前端 *.test.tsx 文件)和后端测试(pytest)。
技能文档给出的技术栈如下表。需要说明的是,版本号以当前仓库实际依赖为准:
| 工具 | 技能文档记录 | 当前仓库实际 | 用途 |
|---|---|---|---|
| Playwright | 1.59.1 | 1.60.0 | E2E 测试运行器 + 浏览器自动化 |
| Chromium | (内置) | (内置) | 默认浏览器,Firefox/Safari 被禁用 |
| 自定义 fixtures | tests/fixtures.ts |
同左 | 自动检测 API 错误与 flow 执行失败 |
当前 package.json 中 "@playwright/test": "1.60.0",且 devDependencies 中的 playwright 同为 1.60.0。配置文件中 Firefox/Safari 项目均被注释掉,只启用 Chromium 项目。
二、运行命令与 WebServer 自启动机制
2.1 常用命令
# 运行全部 E2E 测试
npx playwright test
# 按标签过滤运行
npx playwright test --grep "@release"
npx playwright test --grep "@workspace"
npx playwright test --grep "@starter-projects"
# 运行单个测试文件
npx playwright test tests/core/features/run-flow.spec.ts
# 调试模式(headed 浏览器 + 单步)
npx playwright test --debug
# 查看 HTML 报告
npx playwright show-report
# 更新快照(如有使用)
npx playwright test --update-snapshots
仓库还提供了一键脚本 run-tests.sh:它负责安装 Playwright 浏览器、通过 make frontend 启动前端、用 poetry run langflow run --backend-only --port 7860 启动后端(设置 LANGFLOW_DATABASE_URL=sqlite:///./temp 与 LANGFLOW_AUTO_LOGIN=True),最后执行 npx playwright test tests/core --project=chromium,并在退出时通过 trap 清理 7860/3000 端口与临时数据库。tests/README.md 则建议日常开发用 make tests_frontend 入口运行。
2.2 Playwright 自动拉起的服务栈
从 playwright.config.ts 的 webServer 数组看,Playwright 会按顺序自动启动三个服务:
-
OpenAI 兼容 mock 服务:
node tests/fixtures/openai-compatible-server.mjs,健康检查地址http://127.0.0.1:8787/health。这使得 E2E 测试中的 LLM 调用不依赖真实 OpenAI 凭证。 -
后端 API(uvicorn,7860 端口):
uv run uvicorn --factory langflow.main:create_app \ --host localhost --port 7860 --loop asyncio \ --log-level error --no-access-log注入的关键环境变量(见配置文件 L124-L137):
环境变量 值 作用 LANGFLOW_DATABASE_URLsqlite:///./temp使用临时 SQLite 数据库,测试后清理 LANGFLOW_AUTO_LOGINtrue跳过登录页,配合 awaitBootstrapTestLANGFLOW_SUPERUSER/LANGFLOW_SUPERUSER_PASSWORDlangflow/ 测试口令提供固定超级用户 LANGFLOW_DEACTIVATE_TRACINGtrue关闭追踪,减少噪声 LANGFLOW_LOG_LEVELERROR降低日志量 OPENAI_API_KEY/OPENAI_BASE_URL本地回环 key / http://127.0.0.1:8787/v1把模型调用指向上面的 mock 服务 LANGFLOW_A2A_ENABLEDtrue暴露 A2A 发现 + JSON-RPC 端点,供 Agent 标签页测试发布并调用真实 agent 后端启动超时设为
120 * 750毫秒量级的宽裕值(timeout: 120 * 750),并允许复用已存在的服务器(reuseExistingServer: true),避免重复冷启动。 -
前端(
npm start,即 Vite,3000 端口):通过VITE_PROXY_TARGET=http://localhost:7860把/api请求代理到后端。
2.3 关键配置项
来自 playwright.config.ts 的实际取值:
| 配置 | 值 | 说明 |
|---|---|---|
fullyParallel |
true |
测试文件并行执行 |
timeout |
5 * 60 * 1000(5 分钟) |
Flow 构建可能较慢,防止误报超时 |
retries |
1 |
当前配置固定 1 次重试(技能文档曾记录为本地 3 次/CI 2 次,以当前配置为准) |
workers |
2 |
平衡速度与资源占用 |
actionTimeout |
20000(20 秒) |
单个 action(click、fill 等)的超时 |
trace |
on-first-retry |
首次重试时采集 trace,便于事后调试 |
baseURL |
http://localhost:${PORT || 3000}/ |
指向 Vite dev server |
forbidOnly |
CI 时强制开启 | 防止 test.only 被意外提交 |
testIgnore |
**/live/** |
排除 live 目录(连接真实外部服务的测试) |
reporter |
CI 用 blob;本地用 list + html |
本地报告输出到 playwright-report/ |
Chromium 项目额外授予了 clipboard-read / clipboard-write 权限,用于覆盖剪贴板相关交互。
三、目录结构与文件命名
src/frontend/tests/
├── fixtures.ts # 自定义 fixture:错误检测 + a11y 扫描钩子
├── globalTeardown.ts # 收尾:删除临时数据库
├── a11y/ # 可访问性扫描辅助
├── assets/ # 测试用文件资源(uploadFile 的来源目录)
├── live/ # 连接真实外部服务的测试(默认被忽略)
├── core/
│ ├── features/ # 主功能测试(run-flow、playground 等)
│ ├── integrations/ # Starter project / 模板测试
│ ├── regression/ # Bug 回归测试
│ └── unit/ # 组件级 Playwright 测试
└── utils/ # 37+ 个共享辅助函数
extended/ 目录下平行组织 features/、integrations/、regression/ 三类"扩展"测试(MCP、auto-save 等较新特性)。
文件命名约定:
- kebab-case +
.spec.ts后缀:run-flow.spec.ts、playground.spec.ts、flow-lock.spec.ts; - 模板测试允许带空格的文件名:
Document QA.spec.ts、Social Media Agent.spec.ts; - 分片并行测试:
chatInputOutputUser-shard-0.spec.ts; - E2E 用
.spec.ts(Playwright 约定),单元测试用.test.tsx(Jest 约定),两者不可混用。
四、测试编写范式(Test Anatomy)
以下四种范式直接继承自 SKILL.md,并标注了当前源码状态。
4.1 基础测试
import { expect, test } from "../../fixtures";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
test(
"user should be able to run a flow successfully",
{ tag: ["@release", "@workspace"] },
async ({ page }) => {
await awaitBootstrapTest(page);
// Arrange: 创建 flow
await page.getByTestId("blank-flow").click();
// Act: 添加组件并运行
await page.getByTestId("sidebar-search-input").fill("Chat Output");
// ... setup ...
// Assert: 验证构建成功
await expect(page.getByTestId("build-status-success")).toBeVisible({ timeout: 30000 });
},
);
awaitBootstrapTest 是当前每个测试的强制入口。从 await-bootstrap-test.ts 的源码看,它做了三件事:page.goto("/") 打开应用,等待 [data-testid="mainpage_title"] 出现(30 秒超时,seedFlowIfEmpty 默认开启,为空工作区播种 flow),然后打开模板选择弹窗(可用 skipModal: true 跳过)。它存在的原因是:没有这一步,测试会与前端初始化竞争——组件可能未渲染、store 可能未水合、API 调用可能未完成。技能文档中几乎每条"元素找不到"的偶发失败都归因于缺少这一步。
4.2 使用 test.describe 组织
test.describe("Flow Lock Feature", () => {
test(
"should lock and unlock a flow",
{ tag: ["@release", "@api"] },
async ({ page }) => { /* ... */ },
);
test(
"should prevent editing when locked",
{ tag: ["@release"] },
async ({ page }) => { /* ... */ },
);
});
4.3 串行模式(依赖顺序的测试)
test.describe.configure({ mode: "serial" });
test("step 1: create flow", async ({ page }) => { /* ... */ });
test("step 2: edit flow", async ({ page }) => { /* ... */ });
test("step 3: delete flow", async ({ page }) => { /* ... */ });
4.4 事件投递模式包装器(注意当前实现已简化)
技能文档描述 withEventDeliveryModes 会把测试在 streaming / polling / direct 三种事件投递模式下各跑一遍(通过拦截 /api/v1/config 路由自动配置)。但阅读当前源码 withEventDeliveryModes.ts 可以看到,该包装器现在是一个兼容性 no-op shim:其注释明确说明 "v2 workflows endpoint replaced the three modes with a single AG-UI SSE path",即 v2 workflows 端点已把三种投递模式统一为单一的 AG-UI SSE 通道,包装器目前只注册一次测试,保留签名以兼容所有既有调用点:
export function withEventDeliveryModes(
title: string,
config: TestConfig,
testFn: TestFunction,
) {
test(title, config, async ({ page }) => {
await testFn({ page });
});
}
因此从源码结构看,新测试继续按原有签名调用它不会出错,但不要再依赖它产生 3 倍用例;三种模式的差异覆盖逻辑已由后端统一的 SSE 通道取代。
五、标签(Tag)体系
tests/README.md 与技能文档一致地规定:每个测试必须携带 @release 标签——release 运行按该标签 grep 过滤,未打标签或标签拼错的 spec 会静默地从发布覆盖中消失(文档特别提醒:是 @starter-projects,不是 @starter-projectss)。除此之外只允许以下六个标签,不得自创:
| 标签 | 用途 | 适用场景 |
|---|---|---|
@release |
属于发布运行(每个 spec 必需) | 所有测试 |
@workspace |
工作区/flow 管理 | 创建、编辑、删除 flow |
@api |
依赖 API 的功能 | 调用后端端点的测试 |
@database |
数据库操作 | 涉及持久化的测试 |
@components |
组件级测试 | 单个组件的行为 |
@starter-projects |
模板/起步项目测试 | 预置 flow 模板 |
// 正确:打标签
test("my feature test", { tag: ["@release", "@workspace"] }, async ({ page }) => { ... });
// 错误:无标签,无法被过滤
test("my feature test", async ({ page }) => { ... });
六、自定义 Fixture:自动错误感知
这是 Langflow E2E 体系最有价值的部分。所有 spec 必须从 ../../fixtures 导入 test 与 expect,而不是从 @playwright/test 导入——后者会绕过全部错误检测:
// 正确
import { expect, test } from "../../fixtures";
// 错误——绕过错误检测,可能产生"静默通过"
import { expect, test } from "@playwright/test";
6.1 为什么需要它
没有自定义 fixture 时,测试可能在以下情况下依然"通过":
- 后端返回 500,但测试只检查了 UI 文案;
- flow 构建因 Python 异常静默失败,但测试只检查了按钮状态;
- 资源被删除后 API 返回 404,测试根本没检查响应。
6.2 检测行为(对照 fixtures.ts 源码)
fixtures.ts 通过 base.extend 重写了 page fixture(L86-L525),在每个测试的 page 生命周期内挂接 request / response / requestfinished / requestfailed 监听器,核心逻辑 inspectResponse(L186-L335)分两条线工作:
(1)HTTP 状态码监控:凡是 URL 包含 /api/ 且状态码 ≥ 400 的响应都会被记录。4xx 进入 clientErrors 列表(附 method/path/status/脱敏后的响应体)并在测试结束后作为 api-4xx-responses 附件写入报告;5xx 则进入"服务端错误契约"(server error contract,实现见 server-error-contract.mjs):
| 状态码 | 含义 | 失败原因 |
|---|---|---|
| 400 | Bad Request | 客户端发送了非法数据——通常是前端 bug |
| 404 | Not Found | 资源不存在——通常是过期 ID 或缺少前置步骤 |
| 422 | Validation Error | Pydantic 校验失败——通常是 schema 不匹配 |
| 500 | Internal Server Error | 后端崩溃——永远是 bug |
未声明的 5xx、以及已声明但未观察到的 5xx(例如用 page.expectServerError({ method, path, status, count }) 注册了预期却未发生)都会让 fixture 在 teardown 阶段抛出 Server-error contract failed 错误,并列出每一笔未匹配项。
(2)流式/执行类响应的错误解析:对状态为 200 且路径包含 /events?event_delivery=、/build/ 或 /run/ 的响应,fixture 先排除 text/event-stream、application/grpc、application/octet-stream、application/x-ndjson 等"真流式"内容(这些由别的机制跟踪),然后对有限响应体逐行尝试 JSON 解析,命中以下任一情况即记为 flow 执行错误:
json.data.build_data.params以Error开头(构建错误);json.data.error === true或json.error === true(记录error_message);- 原始文本匹配 Python 异常模式:
NameError:、TypeError:、ValueError:、AttributeError:、ImportError:、KeyError:、An error occured ...。
响应体读取有 2 秒超时(RESPONSE_BODY_READ_TIMEOUT_MS = 2000,见 L42-L44):流式响应仍在写入时读取会超时,此时跳过 body 解析并打警告,避免 fixture 被长流卡死。teardown 阶段还有 2 秒的"在途请求排空"窗口(API_REQUEST_DRAIN_TIMEOUT_MS),确保跟随请求(如 404 后的重试)的响应仍可被观察到。
6.3 允许预期错误
测试 error handling 本身时需要显式放行。fixture 在 page 上注入 allowFlowErrors 方法(L128-L130):
test("should show error message on invalid component config", { tag: ["@release"] }, async ({ page }) => {
page.allowFlowErrors(); // 仅为本测试放行 flow 错误
await awaitBootstrapTest(page);
// ... 触发错误的操作 ...
await expect(page.getByText(/error/i)).toBeVisible();
});
注意边界:allowFlowErrors() 只抑制 flow 执行错误,HTTP 5xx 仍然会失败——服务端崩溃不属于"预期行为"。
错误报告是聚合式的:测试函数结束后,fixture 把收集到的错误拼成描述性消息抛出,形如:
Test failed due to 2 flow execution error(s):
- /api/v1/build/abc123/flow
Traceback (most recent call last)...
If this error is expected, call page.allowFlowErrors() at the start of your test.
这样开发者不必在每个测试里手写响应断言就能定位根因。
6.4 附带能力:a11y 扫描与 CPU 节流
同一 fixture 还提供两个源码级能力:
- 可访问性扫描钩子
page.runA11yScan(label, options?):由RUN_A11Y=true开启(使用accessibility-checker包),RUN_A11Y_ASSERT=true时进一步断言新增违规数为 0,扫描摘要会作为附件写入报告(L139-L183)。配套聚合脚本见npm run a11y:report/a11y:html-report/a11y:job-summary。 - CPU 节流:
LF_CPU_THROTTLE=<rate>环境变量可让 Chromium 通过 CDPEmulation.setCPUThrottlingRate降速,用于复现慢机器(如 Windows CI)上的竞态条件(L76-L108)。
七、选择器策略与 data-testid 目录
7.1 优先级
getByTestId— 最稳定,占 Langflow E2E 使用量的绝大多数;getByRole— 按钮、标题、表单元素;getByText— 可见文本内容;waitForSelector— CSS 选择器与动态元素;locator— 复杂选择器(CSS、XPath)。
7.2 data-testid 命名约定
完整目录见 selectors.md。核心前缀约定(kebab-case + 类型前缀):
| 前缀 | 元素类型 | 示例 |
|---|---|---|
input- |
文本输入 | input-chat-playground、input-flow-name |
button- / button_ |
动作按钮 | button-send、button_run_chat output |
icon- |
图标按钮 | icon-Globe、icon-Lock、icon-ChevronLeft |
popover-anchor-input- |
组件参数字段 | popover-anchor-input-openai_api_key |
add-component-button- |
拖拽添加按钮 | add-component-button-chat-output |
card- |
flow/组件卡片 | card-my-flow-name |
title- |
画布节点标题 | title-OpenAI、title-Chat Output |
handle- |
连接 handle | handle-{component}-{shownode}-{field}-{direction} |
show |
字段可见性开关 | showmodel_name、showtemperature |
常用选择器速查:
画布与导航:blank-flow(新建空白 flow)、sidebar-search-input(组件搜索)、canvas_controls_dropdown(画布控制菜单)、fit_view / zoom_out / zoom_in、react-flow-id(ReactFlow 容器,拖拽目标)、inspector-toggle。
组件字段:popover-anchor-input-{fieldname}(参数输入框,字段名与 name 属性一致)、input-chat-playground、div-chat-message。
动作:add-component-button-{component}、button-send、button_run_{component}、publish-button、save-flow-button、edit-fields-button、playground-btn-flow-io(需用 dispatchEvent("click") 关闭)。
弹窗与面板:modal-title、icon-Globe(全局变量)、icon-Lock(flow 锁)、session-selector、lock-flow-switch、input-flow-name、input-flow-description。
7.3 重要陷阱:全局变量下的 badge 模式
当组件字段选中了全局变量(load_from_db: true + value: "OPENAI_API_KEY")时,字段渲染的是 badge 而不是 <input>——此时 getByTestId("popover-anchor-input-api_key") 找不到元素,因为它根本不在 DOM 中。预置了全局变量的模板:Market Research、Price Deal Finder、Research Agent;未预置(输入框正常渲染)的模板:Instagram Copywriter。这条规则同时解释了为什么 addOpenAiInputKey(page) 辅助函数在 badge 模式下会失效。
新增 data-testid 的判据(三条同时满足才加):E2E 需要交互该元素、没有稳定的 role/text 替代、元素是动态渲染需要稳定锚点。格式为 {type}-{descriptive-name},禁止 btn1、input、wrapper 这类无信息量命名。
八、核心辅助函数(tests/utils/)
共享辅助函数位于 src/frontend/tests/utils/(37+ 个,逐函数详解见 helpers.md)。技能文档给出的速查表:
| 函数 | 作用 | 使用时机 |
|---|---|---|
awaitBootstrapTest(page) |
等待应用完全加载 | 每个测试开头必调 |
initialGPTsetup(page) |
完整流水线:adjustView → updateComponents → selectModel → addKey → adjustView → unselectNodes | 需要 OpenAI 配置的测试 |
adjustScreenView(page, opts?) |
适配视图 + 缩小 | 向画布添加组件之后 |
zoomOut(page, times) |
缩小 N 次 | 组件过小点不中时 |
selectGptModel(page) |
为所有 Language Model 节点选 gpt-4o-mini | 依赖 GPT 的测试 |
addOpenAiInputKey(page) |
为所有 openai_api_key 字段填入 OPENAI_API_KEY | 需要 API key 的测试 |
enableInspectPanel(page) |
打开检查面板 | 必须在 edit-fields-button 之前调用 |
disableInspectPanel(page) |
关闭检查面板 | 清理阶段 |
updateOldComponents(page) |
存在过期组件时点击 "Update all" | 加载已保存 flow 之后 |
unselectNodes(page) |
点击空白画布取消所有选中 | 节点操作之后 |
renameFlow(page, { flowName }) |
重命名当前 flow | flow 管理测试 |
uploadFile(page, filename) |
从测试资源目录上传文件 | 文件上传测试 |
withEventDeliveryModes(...) |
事件投递模式包装(当前为 no-op shim,见 4.4 节) | 既有 starter project 测试 |
tests/README.md 额外强调了一个评审惯例:新 spec 必须复用共享辅助函数(awaitBootstrapTest、openStarterProject、addComponentFromSidebar、sendPlaygroundMessage、setupDeploymentMocks),手抄 bootstrap / 侧边栏拖拽 / 模板 / Playground / 路由 mock 代码块是套件中样板代码的最大来源,评审时应直接指出。
8.1 initialGPTsetup 的可选步骤
await initialGPTsetup(page); // 执行全部步骤
await initialGPTsetup(page, {
skipAdjustScreenView: true,
skipUpdateOldComponents: true,
skipSelectGptModel: true,
});
其六步顺序有讲究:先更新过期组件再选模型,可避免模型下拉框停留在旧组件定义的陈旧列表;选 gpt-4o-mini 则是兼顾低成本与快速响应。
8.2 检查面板模式(关键约束)
// 必须先启用检查面板
await enableInspectPanel(page);
// 点击节点选中
await page.getByTestId("title-OpenAI").click();
// 打开字段编辑器
await page.getByTestId("edit-fields-button").click();
// 切换字段可见性
await page.getByTestId("showmodel_name").click();
// 关闭字段编辑器
await page.getByTestId("edit-fields-button").click();
若跳过 enableInspectPanel(page),edit-fields-button 根本不会出现在 DOM 中——检查面板未开启时该按钮不存在,这是新写测试最常见的失败点之一。
九、跳过测试与清理
// 环境变量缺失时跳过
test.skip(!process?.env?.OPENAI_API_KEY, "OPENAI_API_KEY required to run this test");
// 无条件跳过(必须给出原因)
test.skip(true, "Feature not yet implemented with new designs");
收尾清理由 globalTeardown.ts 完成:所有测试结束后删除 src/frontend/temp 临时数据库目录。源码显示它针对 Windows 做了专门处理——uvicorn 进程可能仍持有 SQLite 文件句柄,POSIX 允许删除打开中的文件而 Win32 不允许(表现为 EBUSY/EPERM),因此 teardown 采用"指数退避重试 5 次 → 逐文件兜底删除 → 永不抛错"的策略,最坏情况下留下目录交由运行器工作区清理。
十、编写高质量 E2E 测试的规范
应做(Do)
- 每个测试都打
@release标签(外加适用的领域标签); - 从
../../fixtures导入,不从@playwright/test导入; - 以
awaitBootstrapTest(page)开头——永远如此; - 用
getByTestId获取稳定选择器; - 为异步操作设置显式超时:
waitForSelector与expect(...).toBeVisible()都要带timeout; - 测试完整用户路径:setup → action → verification;
- 涉及 flow 执行(chat、build)的测试沿用
withEventDeliveryModes调用约定(当前为单次执行,见 4.4 节)。
不应做(Don't)
- 不要用
page.waitForTimeout()(除非绝对必要)——优先waitForSelector或expect().toBeVisible(); - 不要硬编码 API key——从
process.env.OPENAI_API_KEY读取(webServer 配置已注入本地回环 key); - 不要无理由跳过测试——
test.skip()的第二个参数永远必填; - 不要从
@playwright/test导入——使用自定义 fixtures; - 不要忘
enableInspectPanel(page)(访问edit-fields-button前); - 不要假设输入框存在——全局变量选中时渲染的是 badge。
对抗性场景(Challenge Tests)
E2E 测试同样应覆盖对抗性输入,技能文档列出的五类:
- 非法输入:粘贴 1 万字符、特殊字符(
<script>alert(1)</script>)、空提交; - 网络中断:构建中途断连时的表现;
- 权限边界:用户能否通过直接 URL 访问他人 flow;
- 并发操作:双击删除、快速连发消息;
- 错误恢复:500 错误后 UI 是否能优雅恢复(注意:自定义 fixture 会自动把未声明的 500 判为失败,这类测试需配合
expectServerError声明预期)。
十一、延伸阅读(仓库内参考文件)
| 文件 | 内容 |
|---|---|
| SKILL.md | 本文的技能文档骨架:适用场景、命令、标签、规范 |
| selectors.md | 完整 data-testid 目录与命名规范 |
| helpers.md | 37+ 辅助函数的逐函数文档与"何时新建辅助函数"准则 |
| fixtures.md | 自定义 fixture 错误检测行为详解 |
| playwright.config.ts | 运行配置与 webServer 三服务自启动 |
| fixtures.ts | 响应监控、错误契约、a11y 钩子源码 |
| globalTeardown.ts | 临时数据库清理与 Windows 兼容处理 |
| tests/README.md | 辅助函数复用评审惯例与标签规则 |
| run-tests.sh | 一键启动前后端并跑 core 套件的脚本 |
整体来看,Langflow 的 E2E 体系把"测试失败原因"从人工排查变成了契约化自动检测:标签决定发布覆盖面,fixture 决定静默失败无处藏身,选择器目录决定测试的长期稳定性,而 webServer 配置 + 回环 mock 服务则保证测试栈在无需真实 LLM 凭证的前提下完整可复现。
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 StartedRust0623
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