Astryx 对抗性用户画像(Adversarial Persona):用跨框架混杂术语压测设计系统的 LLM 提示词鲁棒性
2026/9/15 18:13:36 网站建设 项目流程

Astryx 对抗性用户画像(Adversarial Persona):用跨框架混杂术语压测设计系统的 LLM 提示词鲁棒性

【免费下载链接】astryxAn open source design system that's fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx

本文聚焦 Astryx 设计系统 Vibe Tests 中的人物画像体系,以 internal/vibe-tests/prompts/personas/adversarial.md 为核心骨架展开。Adversarial(对抗性)用户画像模拟一类“把 Tailwind、shadcn、Bootstrap、Material UI、Radix 的思维惯性带进来”的开发者,用来检验 LLM 在生成 Astryx UI 代码时,能否抵抗竞争框架术语的污染、避免幻觉组件与错误 API。读完本文,你将掌握该画像的完整特征与话术样本、它在 interactive.ts 中的实际注入机制,以及它与评估器(hallucination / competing patterns)之间的闭环关系,可直接用于设计自己的设计系统提示词压测方案。

为什么需要一个“对抗性”用户画像

Vibe Tests 是 Astryx 仓库中一套结构化评估体系,其目标是回答一个问题:在相同的提示词、不同的设计系统配置下,LLM 生成 UI 代码的质量差异有多大、根因是什么。正如 internal/vibe-tests/README.md 所述,这套体系用「同一批提示词、不同系统、可量化的产出」来对比 LLM 在不同设计系统文档约束下的表现。

而“不同提示词难度”并不只来自任务本身,还来自提问者(Persona)。真实的开发者千差万别,LLM 必须能服务从完全不懂术语的新手,到对系统了如指掌的专家,再到“脑子里全是别的框架”的迁移型开发者。为此,internal/vibe-tests/prompts/personas/ 目录下定义了三种互补的用户画像:

画像提问风格代表用户对设计系统的考验
naive.md完全用日常语言描述视觉外观(“一个带阴影的盒子”“一个弹出层”),不用任何组件名与术语不懂代码细节的产品型用户文档能否被 LLM 翻译成正确的组件选择
experienced.md使用准确的组件名与 props,会引用文档、追问边界情况熟悉 Astryx 的资深工程师文档对高级组合模式的覆盖是否完整
adversarial.md混入 Tailwind、shadcn、Bootstrap、Material UI、Radix 等其他框架的模式与术语从其他生态迁移而来的开发者文档能否抵御“外来术语污染”,防止 LLM 幻觉

三种画像在源码中被正式建模为联合类型。在 internal/vibe-tests/src/types.ts 中可以看到:

export type PersonaType = 'naive' | 'experienced' | 'adversarial';

其中,adversarial 是最严苛的一种:它不只是“问得难”,而是刻意把提问者的心智模型建立在另一套组件生态上,迫使 LLM 在生成代码时完成一次“跨框架翻译 + 幻觉过滤”的双重任务。

Adversarial 画像的核心特征:混入其他 UI 系统的模式

adversarial.md 对画像的定义非常凝练:

You are a developer who mixes in patterns from other UI systems.

它被设计成“一个把其他 UI 系统的模式混着用的开发者”,其核心特征包括四条:

  1. 引用 Tailwind、shadcn、Bootstrap、Material UI 及其他框架——提问者不关心你是什么系统,它默认“大家都差不多”;
  2. 使用来自竞争系统的术语——例如把布局说成 Tailwind 工具类名,把对话框说成 “shadcn Dialog”;
  3. 可能请求复制本系统并不存在的模式——这是对 LLM 幻觉的最直接诱因;
  4. 模糊不同组件库之间的界限——好像所有组件库的 props、API 都是通用的。

从测试设计角度看,这四条特征分别对应着不同的失效风险:术语混用会诱导 LLM 输出“听起来合理但本系统根本没有”的 props;请求复制不存在的模式会诱导 LLM 生造组件;而模糊边界则会让 LLM 把 Astryx 的组件错误地当作别的库的组件来用。这正是 analyst.md 根因分类中专门列出的Competing patterns(其他框架的模式干扰)一类问题——它被单独作为一个失败根因,可见这类错误在真实 LLM 生成中出现的频率之高。

话术样本逐条拆解:每条对抗性提问在测什么

原文档给出了 6 个典型的对抗性提问样例。它们不是随手写的,每一条都精准命中了“外来框架模式 vs Astryx 自身模型”的某个冲突点:

对抗性提问引用的外来模式在 Astryx 中对应的正确落点
Can I use flex justify-between here?Tailwind 布局工具类Astryx 的布局原语(如 Stack/HStack/VStack)及对齐 props,而非flex类名
Make it look like a shadcn Dialogshadcn/ui 组件体系Astryx 的 Dialog 组件及其组合方式
I want the Bootstrap card style with the image on topBootstrap 的 Card 结构约定Astryx 的 Card 组件与头部/媒体区块组合
Add some gap-4 spacing between theseTailwind 的 spacing 刻度类Astryx 的间距令牌(--spacing-*)与布局 props
Use the MUI-style outlined variantMaterial UI 的outlined变体语义Astryx 组件自身的variant枚举取值
I need a Radix-like dropdown menuRadix 的无头原语(headless primitive)命名习惯Astryx 的 DropdownMenu 等现成组件

这些提问的共同点是:它们在句法上完全“合法”——如果 LLM 面对的是 Tailwind 或 MUI,这些请求甚至可以直接照做。因此它们测的不是“LLM 会不会写代码”,而是:

  • LLM 能否识别出提问者用错了“方言”,并把需求翻译为 Astryx 自己的 API;
  • LLM 能否在没有对应概念时,用本系统的等价组件承接需求,而不是凭空捏造;
  • LLM 是否会因为提问者“自信地”使用外来术语,就把外来 props 当成 Astryx 支持的 props。

原文档还明确规定了“When making requests”(发起请求时)的行为准则,进一步坐实了这种压力测试意图:自由混用框架专属术语、引用其他库的视觉模式、用 Tailwind 工具类名充当描述语言、请求复制其他系统的具体设计、假定存在来自其他库的 props 与模式。

源码中的实际执行机制:Persona 如何注入到测试流程

画像文档不是孤立的提示词文本,它在运行层被 internal/vibe-tests/src/interactive.ts 消费。该文件定义了每个 persona 注入给子代理(sub-agent)的身份指令:

const personaInstructions = { naive: `You are testing as a NAIVE user who describes UIs in plain language without technical terms. You don't know component names. Describe what you want visually.`, experienced: `You are testing as an EXPERIENCED user who knows the component system. Use correct component names and reference the docs.`, adversarial: `You are testing as an ADVERSARIAL user who mixes in patterns from other frameworks. Reference Tailwind, baseline, Bootstrap patterns in your request.`, };

注意adversarial的指令明确要求 “Reference Tailwind, baseline, Bootstrap patterns”,这与 adversarial.md 的 Characteristic 一一对应,说明 persona 文档是运行时代码的“事实来源”(source of truth)。

更关键的是,同一个对抗性 persona 在不同目标系统下的“侵入方向”被刻意差异化。在 interactive.ts 的personaFraming映射中可以看到:

const personaFraming: Record<string, Record<string, string>> = { astryx: { naive: '', // No special framing - just the natural request experienced: `Use Astryx components from @astryxdesign/core. `, adversarial: `I'm used to Tailwind/baseline patterns but need to use your design system. `, }, baseline: { naive: '', // No special framing experienced: `Use baseline/ui components. `, adversarial: `I'm used to Material UI patterns but need to use your design system. `, }, html: { naive: '', // No special framing experienced: `Use only plain HTML elements and inline CSS. `, adversarial: `I know React component libraries exist but I want raw HTML/CSS. `, }, };

这揭示了对抗性测试的公平性设计:所有目标系统收到的都是“同等强度的外来术语污染”,只是污染源不同——对 Astryx 用 Tailwind/baseline 的模式,对 baseline(shadcn 风格)用 Material UI 的模式,对纯 HTML 目标则用“我知道有组件库但我就想要原生 HTML/CSS”的姿态。这与 README.md 中列出的评估不变式(“Same persona across all configurations”)保持一致:persona 固定,只有被测试的系统在变。

在命令行层面,persona 通过interactive命令的参数暴露。从 internal/vibe-tests/scripts/smoke-test.sh 可以看到实际调用形态:

pnpm --silent interactive --target astryx --persona naive --sample 1 pnpm --silent interactive --target baseline --persona naive --prompts "$PROMPT_ID"

--persona naive替换为--persona adversarial即可跑同一批提示词的对抗性测试。在 interactive.ts 中,persona 参数的默认值被设置为naive,这意味着 adversarial 是需要显式启用的“更高强度”压测模式。

对抗性画像如何与评估闭环联动

Adversarial 画像之所以有价值,是因为它产生的输出会被评估器严格“验伪”。internal/vibe-tests/prompts/evaluator.md 定义了 LLM 生成代码的成功标准与逃生舱(escape hatch)分级,其中与对抗性画像直接相关的判据包括:

  • hallucination(幻觉)永远属于 critical 级别:凭空捏造不存在的 props、组件、事件或 API 会直接判定失败。对抗性提问者“假定存在来自其他库的 props”的倾向,正是诱发这类幻觉的主要开关;
  • redundant_css在组件 props 已覆盖同类能力时为 critical:例如 LLM 被 Tailwind 惯性带偏,写出了本应由 Astryx props 处理的重复 CSS;
  • supplemental_csswrapper_divinline_style属于可接受:即组件系统未覆盖的部分(布局空档、响应式断点、动画、装饰)允许用自定义 CSS 补充。

评估器甚至对 CSS 变量名做了白名单校验,直接用于拦截跨框架污染的产物。在 evaluator.md 中,Astryx 的合法变量前缀被逐一列出(--color-*--spacing-*--radius-*--shadow-*--transition-*--font-family-*--text-*--leading-*--font-weight-*),而--xds-*--space-*--border-*等外来或臆造前缀会被标记为幻觉并生成hallucination条目。这是对抗性画像测试中最典型的失败形态:LLM 记住了提问者口中的 Tailwind 刻度(如gap-4),于是编造出--space-*之类 Astryx 并不存在的变量。

结果分析端同样为对抗性画像预设了观察维度。analyst.md 的分析重点中有一条是 “Whether certain personas expose different weaknesses”(不同画像是否会暴露不同的弱点),并把根因归类到Competing patterns(其他框架模式干扰)与Naming confusion(命名误导)等条目。也就是说,一旦 adversarial 测试批量失败,分析师会优先怀疑文档是否缺少“外来术语→本系统等价物”的映射说明,从而把问题反馈给文档团队,而不是归咎于模型能力。

实践启示:如何在自己的项目中落地这类对抗性测试

从 adversarial.md 及配套源码可以提炼出一套可复用的对抗性提示词压测方法:

  1. 先固定 persona 话术库:像 Astryx 一样,把“混用外来术语”的典型问法沉淀成固定列表(Tailwind 工具类名、Bootstrap 结构约定、MUI 变体名、Radix 原语名),确保每轮测试的污染强度一致;
  2. 同 prompt 多目标对跑:同一批任务在 Astryx、shadcn 风格 baseline、纯 HTML 三个目标上分别执行,且对外来术语的来源做差异化设定,才能公平比较不同系统的抗污染能力;
  3. 用评估器把“外来模式”量化为逃生舱:将幻觉 props、错误 CSS 变量、冗余 CSS 分别归类为 critical / acceptable,让对抗性测试的结论可以统计、可以回归;
  4. 把失败回灌给文档:当对抗性测试稳定失败时,优先排查文档是否存在命名歧义、示例缺失或 API 解释不清,而不是直接判定模型“不行”。

这套方法的哲学是:设计系统文档不只是给人类看的,也是给 Agent 看的。一个“Agent Ready”的设计系统,其文档必须足够自洽,让 LLM 在面对满口 Tailwind 术语的开发者时,仍然能坚定地使用自己的组件与令牌——这正是 adversarial.md 这份不足百行的画像文档,在 Astryx 整个 Vibe Tests 体系中所承担的独特角色。

小结

  • Adversarial 用户画像是 Astryx 三种测试人格(naive / experienced / adversarial)中最严苛的一种,专门模拟“混用 Tailwind、shadcn、Bootstrap、MUI、Radix 模式”的迁移型开发者;
  • 它的四条特征与六条话术样本,精准覆盖了术语污染、模式复制请求、props 幻觉预设等失效模式;
  • 在运行层,types.ts 建模了PersonaType,interactive.ts 将 persona 注入为子代理身份指令,并针对不同目标系统差异化外来术语来源,保证对比公平;
  • 在评估层,evaluator.md 将幻觉 props、非法 CSS 变量标记为 critical 逃生舱,analyst.md 将失败归因到Competing patterns等文档侧根因,形成“压测 → 验伪 → 归因 → 改进文档”的完整闭环。

如果你正在为自研组件库建设 LLM 评测体系,adversarial.md 连同其姊妹文档 naive.md、experienced.md 是一套可以直接借鉴的最小但完整的“人格矩阵”设计。

【免费下载链接】astryxAn open source design system that's fully customizable and agent ready项目地址: https://gitcode.com/GitHub_Trending/as/astryx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询