From 537224d6acda79123a724e46f53e9d5c8e0344c2 Mon Sep 17 00:00:00 2001 From: Sherry-hue <37186915+Sherry-hue@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:36:56 +0800 Subject: [PATCH] docs(a2ui): add system prompts guides --- packages/genui/a2ui/README.md | 13 +- packages/genui/a2ui/README_zh.md | 13 +- packages/genui/a2ui/docs/catalog-guide.md | 6 +- packages/genui/a2ui/docs/catalog-guide_zh.md | 5 +- packages/genui/a2ui/docs/overview.md | 20 +- packages/genui/a2ui/docs/overview_zh.md | 19 +- packages/genui/a2ui/docs/system-prompts.md | 187 ++++++++++++++++++ packages/genui/a2ui/docs/system-prompts_zh.md | 187 ++++++++++++++++++ 8 files changed, 416 insertions(+), 34 deletions(-) create mode 100644 packages/genui/a2ui/docs/system-prompts.md create mode 100644 packages/genui/a2ui/docs/system-prompts_zh.md diff --git a/packages/genui/a2ui/README.md b/packages/genui/a2ui/README.md index 124a6ba9ba..2b46f8984a 100644 --- a/packages/genui/a2ui/README.md +++ b/packages/genui/a2ui/README.md @@ -86,12 +86,12 @@ generated UI actions through `onAction`. ## What You Own -| Part | Owner | Role | -| ---------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------ | -| `@lynx-js/genui/a2ui` | This package | ReactLynx renderer, `MessageStore`, catalog APIs, built-in components, protocol helpers, and client function entries. | -| `genui a2ui` | GenUI CLI | Build-time commands for generating custom catalog artifacts and A2UI system prompts. | -| Your Agent service | Your application | Receives user prompts/actions, calls a model with the A2UI prompt and catalog, validates output, and returns messages. | -| Your transport adapter | Your application | Calls the Agent service, handles REST or streaming responses, writes messages into `MessageStore`, and forwards actions. | +| Part | Owner | Role | +| ------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `@lynx-js/genui/a2ui` | This package | ReactLynx renderer, `MessageStore`, catalog APIs, built-in components, protocol helpers, and client function entries. | +| `npx @lynx-js/genui a2ui` | GenUI CLI | Build-time commands for generating custom catalog artifacts and A2UI system prompts. | +| Your Agent service | Your application | Receives user prompts/actions, calls a model with the A2UI prompt and catalog, validates output, and returns messages. | +| Your transport adapter | Your application | Calls the Agent service, handles REST or streaming responses, writes messages into `MessageStore`, and forwards actions. | ## First Things To Know @@ -109,4 +109,5 @@ generated UI actions through `onAction`. - [Overview and architecture](./docs/overview.md) - [Catalogs, built-ins, and custom components](./docs/catalog-guide.md) +- [System prompts](./docs/system-prompts.md) - [Open the A2UI playground](https://lynxjs.org/a2ui) diff --git a/packages/genui/a2ui/README_zh.md b/packages/genui/a2ui/README_zh.md index a5e8d1191e..f978288931 100644 --- a/packages/genui/a2ui/README_zh.md +++ b/packages/genui/a2ui/README_zh.md @@ -78,12 +78,12 @@ async function sendPrompt(input: string) { ## 你需要负责什么 -| 部分 | 负责人 | 作用 | -| ---------------------- | --------- | ------------------------------------------------------------------------------------------------------- | -| `@lynx-js/genui/a2ui` | 这个包 | ReactLynx renderer、`MessageStore`、Catalog API、内置组件、协议辅助能力,以及 client function entries。 | -| `genui a2ui` | GenUI CLI | 构建期命令,用来生成自定义 catalog artifacts 和 A2UI system prompts。 | -| 你的 Agent 服务 | 你的应用 | 接收用户 prompt/action,带着 A2UI prompt 和 catalog 调用模型,校验输出,然后返回 messages。 | -| 你的 transport adapter | 你的应用 | 调用 Agent 服务,处理 REST 或流式响应,把 messages 写入 `MessageStore`,并转发 generated UI actions。 | +| 部分 | 负责人 | 作用 | +| ------------------------- | --------- | ------------------------------------------------------------------------------------------------------- | +| `@lynx-js/genui/a2ui` | 这个包 | ReactLynx renderer、`MessageStore`、Catalog API、内置组件、协议辅助能力,以及 client function entries。 | +| `npx @lynx-js/genui a2ui` | GenUI CLI | 构建期命令,用来生成自定义 catalog artifacts 和 A2UI system prompts。 | +| 你的 Agent 服务 | 你的应用 | 接收用户 prompt/action,带着 A2UI prompt 和 catalog 调用模型,校验输出,然后返回 messages。 | +| 你的 transport adapter | 你的应用 | 调用 Agent 服务,处理 REST 或流式响应,把 messages 写入 `MessageStore`,并转发 generated UI actions。 | ## 首次接入要知道 @@ -99,4 +99,5 @@ async function sendPrompt(input: string) { - [概览与架构](./docs/overview_zh.md) - [Catalogs、内置组件与自定义组件](./docs/catalog-guide_zh.md) +- [System Prompts](./docs/system-prompts_zh.md) - [打开 A2UI Playground](https://lynxjs.org/a2ui) diff --git a/packages/genui/a2ui/docs/catalog-guide.md b/packages/genui/a2ui/docs/catalog-guide.md index 503a429308..a9d048ef8f 100644 --- a/packages/genui/a2ui/docs/catalog-guide.md +++ b/packages/genui/a2ui/docs/catalog-guide.md @@ -346,7 +346,7 @@ and pair it the same way you would a built-in. 2. Run the public CLI to emit the JSON: ```bash - genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog + npx @lynx-js/genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog ``` 3. Pair the generated JSON with the component: @@ -358,7 +358,7 @@ and pair it the same way you would a built-in. const catalog = defineCatalog([[MyChart, myChartManifest]]); ``` -`genui a2ui generate catalog` is the user-facing command; +`npx @lynx-js/genui a2ui generate catalog` is the user-facing command; `@lynx-js/genui/a2ui-catalog-extractor` is the TypeDoc-powered engine behind it. Two constraints to keep extraction happy: the component folder name must match the exported function name (`src/catalog/MyChart/index.tsx` exports @@ -396,4 +396,6 @@ All of these are exported from `@lynx-js/genui/a2ui` (and from the - [Overview and architecture](./overview.md) — how a message becomes UI, the responsibility split, and the export map. +- [System prompts](./system-prompts.md) — generate the model instructions + that pair an Agent with your catalog. - [Open the A2UI playground](https://lynxjs.org/a2ui) — try it live. diff --git a/packages/genui/a2ui/docs/catalog-guide_zh.md b/packages/genui/a2ui/docs/catalog-guide_zh.md index 7d24379e70..c0523b86c9 100644 --- a/packages/genui/a2ui/docs/catalog-guide_zh.md +++ b/packages/genui/a2ui/docs/catalog-guide_zh.md @@ -326,7 +326,7 @@ MyChart.displayName = 'MyChart'; 2. 运行公开 CLI 输出 JSON: ```bash - genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog + npx @lynx-js/genui a2ui generate catalog --catalog-dir src/catalog --out-dir dist/catalog ``` 3. 把生成的 JSON 与组件配对: @@ -338,7 +338,7 @@ MyChart.displayName = 'MyChart'; const catalog = defineCatalog([[MyChart, myChartManifest]]); ``` -`genui a2ui generate catalog` 是面向用户的命令; +`npx @lynx-js/genui a2ui generate catalog` 是面向用户的命令; `@lynx-js/genui/a2ui-catalog-extractor` 是它背后由 TypeDoc 驱动的引擎。两条约束 能让抽取顺利进行:组件文件夹名必须与导出的 function 名一致 (`src/catalog/MyChart/index.tsx` 导出 `function MyChart`),并且框架级 props @@ -369,4 +369,5 @@ MyChart.displayName = 'MyChart'; - [概览与架构](./overview_zh.md)——一条 message 如何变成 UI、职责划分,以及 export 映射。 +- [System Prompts](./system-prompts_zh.md)——生成让 Agent 与你的 catalog 配套的模型指令。 - [打开 A2UI playground](https://lynxjs.org/a2ui)——在线体验。 diff --git a/packages/genui/a2ui/docs/overview.md b/packages/genui/a2ui/docs/overview.md index 9e36fda940..af73c7f762 100644 --- a/packages/genui/a2ui/docs/overview.md +++ b/packages/genui/a2ui/docs/overview.md @@ -147,15 +147,15 @@ The package draws a hard line between what it provides and what your application provides. Keeping that line crisp is the reason the runtime stays transport-agnostic and the catalog stays explicit. -| Piece | Runs in | Owner | Responsibility | -| ----------------- | ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| Agent service | Server | Your application | Turns prompts and client actions into validated A2UI message arrays. Prompts the model with the same catalog contract the client renders. | -| Transport adapter | Client shell | Your application | Sends prompts/actions to the Agent over REST/SSE/WebSocket, then writes the returned messages into a `MessageStore`. | -| `MessageStore` | Client | This package | Stores raw A2UI messages in arrival order and notifies subscribers. It does not parse or interpret the protocol. | -| `` | Client | This package | Owns a `MessageProcessor` per mount, consumes new messages, renders the active surface, and forwards generated UI actions through `onAction`. | -| Catalog API | Client + Agent handshake | This package | Maps protocol component/function names to local implementations and optional JSON schemas. Compose it with `defineCatalog` and friends. | -| Built-ins | Client | This package | A2UI v0.9 basic-catalog component renderers, per-component JSON-Schema manifests, and client-side basic-catalog function implementations. | -| `genui a2ui` | Build / setup time | GenUI CLI | Generates custom catalog artifacts and A2UI system prompts. Not required when both Agent and renderer use the built-in basic catalog. | +| Piece | Runs in | Owner | Responsibility | +| ------------------------- | ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Agent service | Server | Your application | Turns prompts and client actions into validated A2UI message arrays. Prompts the model with the same catalog contract the client renders. | +| Transport adapter | Client shell | Your application | Sends prompts/actions to the Agent over REST/SSE/WebSocket, then writes the returned messages into a `MessageStore`. | +| `MessageStore` | Client | This package | Stores raw A2UI messages in arrival order and notifies subscribers. It does not parse or interpret the protocol. | +| `` | Client | This package | Owns a `MessageProcessor` per mount, consumes new messages, renders the active surface, and forwards generated UI actions through `onAction`. | +| Catalog API | Client + Agent handshake | This package | Maps protocol component/function names to local implementations and optional JSON schemas. Compose it with `defineCatalog` and friends. | +| Built-ins | Client | This package | A2UI v0.9 basic-catalog component renderers, per-component JSON-Schema manifests, and client-side basic-catalog function implementations. | +| `npx @lynx-js/genui a2ui` | Build / setup time | GenUI CLI | Generates custom catalog artifacts and A2UI system prompts. Not required when both Agent and renderer use the built-in basic catalog. | A useful way to remember it: **the server decides, the client renders, and the catalog is the contract they agree on.** The catalog is the one piece @@ -307,4 +307,6 @@ Lifecycle notes that save debugging time: - [Catalogs, built-ins, and custom components](./catalog-guide.md) — compose the contract, add manifests, and register your own components. +- [System prompts](./system-prompts.md) — generate the model instructions + that pair an Agent with your catalog. - [Open the A2UI playground](https://lynxjs.org/a2ui) — try it live. diff --git a/packages/genui/a2ui/docs/overview_zh.md b/packages/genui/a2ui/docs/overview_zh.md index 169711c9c6..e6311b6cc3 100644 --- a/packages/genui/a2ui/docs/overview_zh.md +++ b/packages/genui/a2ui/docs/overview_zh.md @@ -140,15 +140,15 @@ SSE、WebSocket,或一个 in-process mock。renderer 不关心 messages 是怎 这个包在「它提供什么」和「你的应用提供什么」之间划了一条硬边界。保持这条边界 清晰,正是运行时保持传输无关、catalog 保持显式的原因。 -| 部分 | 运行位置 | 负责人 | 职责 | -| ----------------- | ------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------- | -| Agent 服务 | Server | 你的应用 | 把 prompt 和 client action 转成经过校验的 A2UI message 数组。使用与 client 可渲染能力一致的 catalog contract 提示模型。 | -| Transport adapter | Client shell | 你的应用 | 通过 REST/SSE/WebSocket 把 prompt/action 发给 Agent,再把返回的 messages 写入 `MessageStore`。 | -| `MessageStore` | Client | 这个包 | 按到达顺序保存原始 A2UI messages 并通知订阅者。它不解析也不解释协议语义。 | -| `` | Client | 这个包 | 每次 mount 拥有一个 `MessageProcessor`,消费新 messages,渲染 active surface,并通过 `onAction` 转发 generated UI action。 | -| Catalog API | Client + Agent handshake | 这个包 | 把协议中的 component/function 名称映射到本地实现和可选 JSON schema。用 `defineCatalog` 等组合它。 | -| 内置能力 | Client | 这个包 | A2UI v0.9 basic-catalog 的组件 renderer、逐组件 JSON-Schema manifest,以及客户端 basic-catalog function 实现。 | -| `genui a2ui` | 构建 / 接入阶段 | GenUI CLI | 生成自定义 catalog artifacts 和 A2UI system prompt。当 Agent 和 renderer 都用内置 basic catalog 时不需要它。 | +| 部分 | 运行位置 | 负责人 | 职责 | +| ------------------------- | ------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------- | +| Agent 服务 | Server | 你的应用 | 把 prompt 和 client action 转成经过校验的 A2UI message 数组。使用与 client 可渲染能力一致的 catalog contract 提示模型。 | +| Transport adapter | Client shell | 你的应用 | 通过 REST/SSE/WebSocket 把 prompt/action 发给 Agent,再把返回的 messages 写入 `MessageStore`。 | +| `MessageStore` | Client | 这个包 | 按到达顺序保存原始 A2UI messages 并通知订阅者。它不解析也不解释协议语义。 | +| `` | Client | 这个包 | 每次 mount 拥有一个 `MessageProcessor`,消费新 messages,渲染 active surface,并通过 `onAction` 转发 generated UI action。 | +| Catalog API | Client + Agent handshake | 这个包 | 把协议中的 component/function 名称映射到本地实现和可选 JSON schema。用 `defineCatalog` 等组合它。 | +| 内置能力 | Client | 这个包 | A2UI v0.9 basic-catalog 的组件 renderer、逐组件 JSON-Schema manifest,以及客户端 basic-catalog function 实现。 | +| `npx @lynx-js/genui a2ui` | 构建 / 接入阶段 | GenUI CLI | 生成自定义 catalog artifacts 和 A2UI system prompt。当 Agent 和 renderer 都用内置 basic catalog 时不需要它。 | 一个好记的方式:**server 决策,client 渲染,catalog 是两边达成一致的 contract。** catalog 是唯一同时活在 wire 两侧的部分——你的 client 注册实现, @@ -285,4 +285,5 @@ MessageStore ──subscribe──► ──► MessageProcessor ── - [Catalogs、内置组件与自定义组件](./catalog-guide_zh.md)——组合 contract、加入 manifest、注册你自己的组件。 +- [System Prompts](./system-prompts_zh.md)——生成让 Agent 与你的 catalog 配套的模型指令。 - [打开 A2UI playground](https://lynxjs.org/a2ui)——在线体验。 diff --git a/packages/genui/a2ui/docs/system-prompts.md b/packages/genui/a2ui/docs/system-prompts.md new file mode 100644 index 0000000000..4d81f6e419 --- /dev/null +++ b/packages/genui/a2ui/docs/system-prompts.md @@ -0,0 +1,187 @@ +# System prompts + +Generate and customize the system instructions that teach an LLM to emit valid A2UI messages. + +Generate a reusable prompt with the CLI for most deployments, or build one programmatically when the backend needs request-specific catalog or policy inputs. The prompt tells the model how to produce A2UI v0.9 JSON. It includes the protocol rules, the component catalog, function signatures, validated examples, and hard constraints that keep the renderer output safe and parseable. + +## 1. CLI + +Use `npx @lynx-js/genui a2ui generate prompt` when the backend only needs a static prompt file. + +Generate a prompt with the built-in A2UI basic catalog: + +```bash +npx @lynx-js/genui a2ui generate prompt --out dist/a2ui-system-prompt.txt +``` + +Print the prompt to stdout: + +```bash +npx @lynx-js/genui a2ui generate prompt +``` + +Append deployment-specific instructions: + +```bash +npx @lynx-js/genui a2ui generate prompt \ + --appendix "Prefer compact mobile layouts for travel booking flows." \ + --out dist/a2ui-system-prompt.txt +``` + +`generate prompt` uses the built-in A2UI basic catalog by default. The generated prompt requires `createSurface.catalogId` to match the catalog id embedded in the prompt. + +### Custom catalogs + +For custom components, first generate catalog artifacts: + +```bash +npx @lynx-js/genui a2ui generate catalog \ + --catalog-dir src/catalog \ + --source src/functions \ + --out-dir dist/catalog +``` + +Then generate the prompt from those artifacts: + +```bash +npx @lynx-js/genui a2ui generate prompt \ + --catalog-dir dist/catalog \ + --catalog-id https://example.com/catalogs/custom/v1/catalog.json \ + --out dist/a2ui-system-prompt.txt +``` + +`--catalog-dir` must point at generated files such as `/catalog.json`. If the catalog also has generated function files under `functions/*.json`, they are included in the prompt as callable function signatures. + +The package exposes the same commands through the `genui` binary after installation, so project scripts may use `genui a2ui ...` when `@lynx-js/genui` is already installed locally. Existing A2UI-only scripts may also use the `a2ui-cli` compatibility alias. + +## 2. Programmatic usage + +Use `@lynx-js/genui/a2ui-prompt` when the backend needs to construct prompts in Node.js code. + +Build the default prompt: + +```ts +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const systemPrompt = buildA2UISystemPrompt(); +``` + +Add request- or deployment-specific instructions: + +```ts +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const systemPrompt = buildA2UISystemPrompt({ + appendix: [ + 'Prefer concise mobile-first layouts.', + 'When the user asks for charts, use LineChart only when numeric series are available.', + ].join('\n'), +}); +``` + +Read a generated custom catalog and build a prompt for it: + +```ts +import { + buildA2UISystemPrompt, + readA2UICatalogFromDirectory, +} from '@lynx-js/genui/a2ui-prompt'; + +const catalog = readA2UICatalogFromDirectory({ + catalogDir: 'dist/catalog', + catalogId: 'https://example.com/catalogs/custom/v1/catalog.json', + label: 'Example app catalog', + version: 'v1', +}); + +const systemPrompt = buildA2UISystemPrompt({ catalog }); +``` + +For fully in-memory catalog construction, use `createA2UICatalogFromManifests(...)` with component JSON schemas and optional function specs, then pass the resulting catalog to `buildA2UISystemPrompt`. + +## What gets generated + +The generated prompt includes: + +- A2UI v0.9 protocol overview and design principles. +- Required server-to-client message types: `createSurface`, `updateComponents`, `updateDataModel`, and `deleteSurface`. +- Required message ordering for a fresh response. +- Data binding rules for `{ "path": "/..." }` values and list children. +- Client action rules for events and function calls. +- A rendered catalog reference with component summaries, props, required fields, container shape, enum values, and function signatures. +- Hard rules for JSON-only output, catalog id matching, flat component trees, `root` component requirements, button labels/actions, modal confirmation flows, image query handling, and action-response patches. +- Validated examples from the catalog, when the catalog provides examples. +- Optional appendix text supplied by the CLI or programmatic API. + +The model should return a JSON array of A2UI messages, not Markdown or prose: + +```json +[ + { + "version": "v0.9", + "createSurface": { + "surfaceId": "main", + "catalogId": "https://a2ui.org/specification/v0_9/basic_catalog.json" + } + }, + { + "version": "v0.9", + "updateComponents": { + "surfaceId": "main", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Hello A2UI" + } + ] + } + } +] +``` + +## Backend usage example + +The prompt can be used with any model provider that accepts a system message. The backend should send the system prompt before user messages and then parse or stream the model output as A2UI JSON. + +```ts +import OpenAI from 'openai'; +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); +const systemPrompt = buildA2UISystemPrompt(); + +export async function POST(req: Request) { + const { messages } = await req.json(); + const completion = await client.chat.completions.create({ + model: process.env.OPENAI_MODEL ?? 'your-model', + stream: true, + messages: [ + { role: 'system', content: systemPrompt }, + ...messages, + ], + }); + + return new Response(completion.toReadableStream(), { + headers: { 'Content-Type': 'text/event-stream' }, + }); +} +``` + +If the backend supports interactive A2UI actions, preserve the conversation history and pass client action messages back to the model. Action responses should update the existing surface with `updateDataModel` and/or `updateComponents` instead of creating a new surface. + +## Choosing an approach + +Use the CLI when: + +- The catalog changes at build time. +- The backend can read a checked-in or generated prompt file. +- Multiple services should share exactly the same prompt text. + +Use programmatic generation when: + +- The catalog, appendix, or safety policy changes per deployment or request. +- The backend already loads generated catalog artifacts. +- You need to compose custom `A2UICatalog` objects in code. + +For custom renderer catalogs and manifest generation, see [Catalogs and manifests](./catalog-guide.md) and [Custom components](./custom-components.md). diff --git a/packages/genui/a2ui/docs/system-prompts_zh.md b/packages/genui/a2ui/docs/system-prompts_zh.md new file mode 100644 index 0000000000..5c61a7ca45 --- /dev/null +++ b/packages/genui/a2ui/docs/system-prompts_zh.md @@ -0,0 +1,187 @@ +# System Prompts + +生成和定制用于指导 LLM 输出合法 A2UI 消息的系统提示词。 + +大多数部署场景可以用 CLI 生成一份可复用的 prompt 文件;如果后端需要按请求、环境或 catalog 动态拼装提示词,也可以在 Node.js 代码里通过 API 构建。生成的 prompt 会告诉模型如何输出 A2UI v0.9 JSON,内容包含协议规则、组件 catalog、函数签名、已验证示例,以及保证渲染输出安全、可解析的硬性约束。 + +## 1. CLI + +如果后端只需要一份静态 prompt 文件,可以使用 `npx @lynx-js/genui a2ui generate prompt`。 + +使用内置 A2UI basic catalog 生成 prompt: + +```bash +npx @lynx-js/genui a2ui generate prompt --out dist/a2ui-system-prompt.txt +``` + +输出到 stdout: + +```bash +npx @lynx-js/genui a2ui generate prompt +``` + +追加部署侧的额外指令: + +```bash +npx @lynx-js/genui a2ui generate prompt \ + --appendix "Prefer compact mobile layouts for travel booking flows." \ + --out dist/a2ui-system-prompt.txt +``` + +默认情况下,`generate prompt` 会使用内置 A2UI basic catalog。生成出的 prompt 会要求 `createSurface.catalogId` 与 prompt 中的 catalog id 一致。 + +### 自定义 catalog + +如果使用自定义组件,需要先生成 catalog 产物: + +```bash +npx @lynx-js/genui a2ui generate catalog \ + --catalog-dir src/catalog \ + --source src/functions \ + --out-dir dist/catalog +``` + +然后基于这些产物生成 prompt: + +```bash +npx @lynx-js/genui a2ui generate prompt \ + --catalog-dir dist/catalog \ + --catalog-id https://example.com/catalogs/custom/v1/catalog.json \ + --out dist/a2ui-system-prompt.txt +``` + +`--catalog-dir` 必须指向生成后的 catalog 目录,例如包含 `/catalog.json` 的目录。如果目录下还有 `functions/*.json` 函数定义文件,它们也会作为可调用函数签名写入 prompt。 + +安装 `@lynx-js/genui` 后,包内也会暴露同样的 `genui` 命令。因此项目脚本里可以使用 `genui a2ui ...`。已有的 A2UI-only 脚本也可以继续使用 `a2ui-cli` 兼容别名。 + +## 2. 程序化用法 + +当后端需要在 Node.js 代码中构建 prompt 时,可以使用 `@lynx-js/genui/a2ui-prompt`。 + +构建默认 prompt: + +```ts +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const systemPrompt = buildA2UISystemPrompt(); +``` + +追加请求级或部署级指令: + +```ts +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const systemPrompt = buildA2UISystemPrompt({ + appendix: [ + 'Prefer concise mobile-first layouts.', + 'When the user asks for charts, use LineChart only when numeric series are available.', + ].join('\n'), +}); +``` + +读取已生成的自定义 catalog,并为它构建 prompt: + +```ts +import { + buildA2UISystemPrompt, + readA2UICatalogFromDirectory, +} from '@lynx-js/genui/a2ui-prompt'; + +const catalog = readA2UICatalogFromDirectory({ + catalogDir: 'dist/catalog', + catalogId: 'https://example.com/catalogs/custom/v1/catalog.json', + label: 'Example app catalog', + version: 'v1', +}); + +const systemPrompt = buildA2UISystemPrompt({ catalog }); +``` + +如果 catalog 已经在内存中,可以使用 `createA2UICatalogFromManifests(...)` 传入组件 JSON Schema 和可选函数定义,构建出 `A2UICatalog` 后再交给 `buildA2UISystemPrompt`。 + +## 生成内容 + +生成的 prompt 会包含: + +- A2UI v0.9 协议概览和设计原则。 +- 必需的服务端到客户端消息类型:`createSurface`、`updateComponents`、`updateDataModel` 和 `deleteSurface`。 +- 新 UI 响应的消息顺序要求。 +- `{ "path": "/..." }` 数据绑定和列表 children 的规则。 +- 客户端 action、event 和 function call 的规则。 +- catalog reference:组件摘要、props、必填字段、容器形态、枚举值和函数签名。 +- 硬性规则:只能输出 JSON、catalog id 必须匹配、组件树必须扁平、必须有 `root` 组件、Button 标签和 action 规则、Modal 确认流程、图片查询处理,以及 action response 的 patch 规则。 +- catalog 提供的已验证示例。 +- CLI 或程序化 API 传入的可选 appendix。 + +模型应该返回 A2UI 消息组成的 JSON 数组,而不是 Markdown 或自然语言说明: + +```json +[ + { + "version": "v0.9", + "createSurface": { + "surfaceId": "main", + "catalogId": "https://a2ui.org/specification/v0_9/basic_catalog.json" + } + }, + { + "version": "v0.9", + "updateComponents": { + "surfaceId": "main", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Hello A2UI" + } + ] + } + } +] +``` + +## 后端接入示例 + +只要模型服务支持 system message,就可以使用生成的 prompt。后端应当先发送 system prompt,再发送用户消息,然后解析或流式转发模型输出的 A2UI JSON。 + +```ts +import OpenAI from 'openai'; +import { buildA2UISystemPrompt } from '@lynx-js/genui/a2ui-prompt'; + +const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); +const systemPrompt = buildA2UISystemPrompt(); + +export async function POST(req: Request) { + const { messages } = await req.json(); + const completion = await client.chat.completions.create({ + model: process.env.OPENAI_MODEL ?? 'your-model', + stream: true, + messages: [ + { role: 'system', content: systemPrompt }, + ...messages, + ], + }); + + return new Response(completion.toReadableStream(), { + headers: { 'Content-Type': 'text/event-stream' }, + }); +} +``` + +如果后端支持 A2UI 交互 action,需要保留会话历史,并把客户端 action 消息继续传回模型。action response 应该针对已有 surface 输出 `updateDataModel` 和/或 `updateComponents`,而不是重新创建一个新 surface。 + +## 如何选择 + +适合使用 CLI 的场景: + +- catalog 在构建时确定。 +- 后端可以读取一份已提交或已生成的 prompt 文件。 +- 多个服务需要共享完全一致的 prompt 文本。 + +适合程序化生成的场景: + +- catalog、appendix 或安全策略会按环境或请求变化。 +- 后端本来就会加载生成后的 catalog 产物。 +- 需要在代码里组合自定义 `A2UICatalog`。 + +自定义 renderer catalog 和 manifest 生成流程可继续阅读 [Catalogs and manifests](./catalogs_zh.md) 和 [Custom components](./custom-components_zh.md)。