ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

用 AI Elements 构建 AI 原生聊天界面:ZCode 中的组件库集成与实践指南

用 AI Elements 构建 AI 原生聊天界面:ZCode 中的组件库集成与实践指南 人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载AI Elements 是一套构建在 shadcn/ui 之上的组件库与自定义注册表为 AI 原生应用提供会话Conversation、消息Message、提示输入PromptInput、工具调用展示Tool、推理过程Reasoning等开箱即用的 React 组件。本文以智谱 AI 的 ZCode 仓库中内置的 ai-elements 技能文档为主体结合仓库内 zcode/ui 包 中实际的本地化集成源码系统讲解 AI Elements 的环境准备、CLI 安装、组件组合用法、可扩展性与定制方式以及常见故障排查方法。读完本文你将掌握如何在 ZCode 这类 AI 编程工作台中快速搭建具备消息流、流式输出、工具调用、附件上传与模型选择能力的完整聊天界面。AI Elements 是什么AI Elements 是一个组件库与自定义注册表custom registry构建在 shadcn/ui 之上目标是把 AI 原生应用中最常复用的界面能力会话列表、消息气泡、输入框、工具执行面板等以「组件即源码」的方式交付给开发者。它与传统 UI 组件库最大的区别在于分发模型组件不是打包进 npm 依赖的黑盒而是通过 CLI 将组件代码直接下载并整合进你的项目目录默认位于/components/ai-elements/也可跟随 shadcn 配置的 components 目录。这意味着组件代码成为你代码库的一部分可以像自己写的代码一样直接阅读、修改与定制使用方式与普通 React 组件完全一致无需额外的 Provider 或全局初始化每个组件尽可能透传原生的 HTML 属性例如Message继承HTMLAttributesHTMLDivElement扩展成本极低。在 ZCode 仓库中这一套组件已经被完整地本地化整合进了zcode/ui包目录为 packages/ui/src/components/ai-elements/包含conversation.tsx、message.tsx、tool.tsx、prompt-input.tsx、reasoning.tsx、attachments.tsx、code-block.tsx、terminal.tsx等 40 余个本地实现文件。每个文件头部都带有明确的来源与授权声明Derived from vercel/ai-elementsCopyright 2023 Vercel, Inc.Apache-2.0由 ZCode 做本地集成与格式化适配完整许可与来源信息可查看仓库根目录的 THIRD-PARTY-NOTICES.md。在 ZCode 中的本地化集成方式从仓库源码可以确认ZCode 的 UI 层已经深度采用了 AI Elementspackages/ui/components.json 在registries字段中注册了ai-elements: https://ai-sdk.dev/elements/api/registry/{name}.json说明该包直接复用了 AI Elements 的官方 registryshadcnCLI 可以按名拉取对应组件packages/ui/package.json 的exports中显式导出了./message指向./src/components/ai-elements/message.tsx依赖中同时包含aiAI SDK v6、use-stick-to-bottom、streamdown、shiki等与 AI Elements 配套的运行时库业务侧已经在真实使用这些组件例如 ToolCallBlocks/ToolCallBody.tsx 从 ai-elements 导入了CodeBlock、MessageResponse、ToolInput、ToolOutput来渲染工具调用结果。从本地实现看ZCode 还做了一些适配性改造以 conversation.tsx 为例它在Conversation上固定了initialinstant与resizeinstant以避免任务切换时「恢复历史消息 → 自动吸底」被 smooth 动画叠加成拖沓的缓动导入方式统一改为带.js后缀的相对 ESM 导入规避 NodeNext 下 package.jsonexports未导出深层路径导致的解析问题。这些都是将上游组件真正落地到生产级 AI 工作台时的典型工程实践。环境准备Prerequisites在安装 AI Elements 之前需要确认项目满足以下条件依赖要求说明Node.js18 或更高版本运行安装 CLI 与构建前端的基础运行时Next.js 项目已初始化组件面向 React 生态示例以 Next.js App Router 展示AI SDK已安装提供useChat、streamText、UIMessage等核心 API组件围绕其数据结构设计shadcn/ui已安装或由安装命令自动安装AI Elements 构建在 shadcn/ui 之上未安装时执行任一安装命令会自动补齐此外官方建议使用 AI Gateway 并在env.local中配置AI_GATEWAY_API_KEY这样可以在不逐个配置各家模型厂商 API Key 的情况下统一调用模型便于快速实验。安装组件安装 AI Elements 组件有两种等价方式效果一致将所选组件的代码与所需依赖写入项目。方式一AI Elements CLI推荐npx ai-elementslatest add component-name例如安装会话与消息组件npx ai-elementslatest add conversation npx ai-elementslatest add message npx ai-elementslatest add prompt-input重要所有 CLI 命令都应使用项目packageManager对应的包运行器即npx ai-elementslatest、pnpm dlx ai-elementslatest或bunx --bun ai-elementslatest。示例统一用npx实际项目中请替换为与你的项目一致的运行器。方式二shadcn/ui CLI如果项目已经采用 shadcn 的工作流可以直接通过 shadcn CLI 安装。前提是在components.json中配置好 AI Elements registry——ZCode 的做法可作参考见 packages/ui/components.json{ registries: { ai-elements: https://ai-sdk.dev/elements/api/registry/{name}.json } }配置完成后shadcn CLI 即可按名拉取 AI Elements 组件。执行成功后终端会显示文件已添加的确认信息随后即可在代码中使用该组件。基础使用五分钟跑通一个对话组件组件安装完成后像使用任何 React 组件一样导入即可。以下是来自技能文档的完整示例保存为conversation.tsx它用Message系列组件渲染useChat返回的流式消息use client; import { Message, MessageContent, MessageResponse } from /components/ai-elements/message; import { useChat } from ai-sdk/react; const Example () { const { messages } useChat(); return ( {messages.map(({ role, parts }, index) ( Message from{role} key{index} MessageContent {parts.map((part, i) { switch (part.type) { case text: return MessageResponse key{${role}-${i}}{part.text}/MessageResponse; } })} /MessageContent /Message ))} / ); }; export default Example;关键点解读Message from{role}按消息角色user/assistant自动切换左右对齐与样式用户消息使用次级背景色助手消息通栏展示MessageContent内容容器负责间距与用户消息的主题色bg-primary等MessageResponse渲染 Markdown 正文默认支持 GFM、数学公式与「不完整 Markdown 智能解析」数据源直接来自 AI SDK 的useChat()messages数组无需二次转换组件与 AI SDK 的数据模型天然对齐。由于组件代码就在你的项目里你可以打开组件文件查看实现也可以按自己的需求直接修改。组件体系一览技能文档在 references/ 目录 下为每个组件提供了独立文档并在 scripts/ 目录 提供可直接运行的示例。以下表格汇总了核心组件及其用途完整列表见 references 目录组件用途参考文档Conversation会话容器自动吸底滚动、空态、滚动按钮、Markdown 导出conversation.mdMessage消息气泡、动作按钮、回复分支、Markdown 渲染message.mdPromptInput输入框 附件上传 提交按钮 模型选择下拉prompt-input.mdTool可折叠的工具调用详情参数、状态、输出/错误tool.mdReasoning流式推理过程展示自动展开/收起reasoning.mdAttachments附件展示网格/行内/列表三种形态attachments.mdCodeBlock代码块语法高亮、行号、复制按钮code-block.mdTerminal流式终端输出支持 ANSI 颜色与自动滚动terminal.mdChain of Thought结构化的分步思考过程展示chain-of-thought.mdSuggestion / Queue / Task 等输入建议、队列状态、任务进度等场景化组件见 references 目录核心组件实战Conversation会话容器Conversation负责包裹消息列表并自动滚动到底部同时提供「不在底部时出现的滚动按钮」。核心子组件与能力ConversationContent内容区负责消息间距与内边距ConversationEmptyState空会话时的引导态title、description、icon均可定制ConversationScrollButton仅在未处于底部时显示点击回到最新消息ConversationDownload把整个会话导出为 Markdown 文件默认文件名conversation.mdmessagesToMarkdown导出逻辑的底层工具函数可自定义消息格式化器例如只取文本部分拼接import { messagesToMarkdown } from /components/ai-elements/conversation; const customMarkdown messagesToMarkdown( messages, (msg, i) [${msg.role}]: ${msg.parts .filter((p) p.type text) .map((p) p.text) .join()}, );底层实现上Conversation基于use-stick-to-bottom库ZCode 本地实现见 conversation.tsx支持contextRef、instance、render prop 等进阶用法滚动按钮通过useStickToBottomContext()读取isAtBottom状态并调用scrollToBottom。一个完整的会话 UI 通常由ConversationPromptInput组合而成消息区负责展示输入区负责提交二者共享 AI SDK 的useChat状态。Message消息展示全家桶Message组件族覆盖了聊天消息展示的大部分需求消息渲染Message角色与对齐、MessageContent内容容器、MessageResponseMarkdown 正文操作按钮MessageActionsMessageAction支持带 tooltip 的 Retry / Copy / Like 等操作label用于无障碍朗读未提供 tooltip 时也作为后备文本回复分支MessageBranch、MessageBranchContent、MessageBranchSelector、MessageBranchPrevious、MessageBranchNext、MessageBranchPage用于在多条候选回复之间切换defaultBranch指定默认分支默认 0onBranchChange监听切换工具栏MessageToolbar以 space-between 布局把操作按钮与分支选择器放在消息下方一行。MessageResponse的 Markdown 渲染值得一提它是流式聊天体验的关键parseIncompleteMarkdown默认true自动修复流式传输中的不完整 Markdown未闭合的代码块、列表等remarkPlugins默认[remarkGfm, remarkMath]与rehypePlugins默认含rehypeKatexGFM 表格、任务列表、删除线与数学公式allowedImagePrefixes/allowedLinkPrefixes限制图片与链接的 URL 前缀defaultOrigin处理相对地址兼顾安全与灵活性components传入自定义 React 组件覆盖 Markdown 元素渲染。在 ZCode 本地实现中见 message.tsx约 1670 行Markdown 渲染链路替换为streamdown全家桶Streamdown配合streamdown/cjk、streamdown/code、streamdown/math、streamdown/mermaid插件语法高亮使用shiki并额外引入了remark-cjk-friendly-gfm-strikethrough提升中文文本的删除线渲染质量——这是针对中文 AI 工作台场景的典型本地化增强。PromptInput带附件的提示输入PromptInput允许用户携带文件附件向大模型发送消息内置 textarea、文件上传、提交按钮与模型选择下拉。组件按头部/主体/底部三段式组织PromptInputHeader附件展示区PromptInputBody自动伸缩的PromptInputTextareaEnter 提交、ShiftEnter 换行PromptInputFooter工具栏PromptInputTools与提交按钮PromptInputSubmit。工具栏能力包括PromptInputActionMenu附件/截图菜单内含PromptInputActionAddAttachments与PromptInputActionAddScreenshotPromptInputButton自定义动作按钮支持带快捷键提示的 tooltip// 简单字符串 tooltip PromptInputButton tooltipSearch the web GlobeIcon size{16} / /PromptInputButton // 带快捷键提示 PromptInputButton tooltip{{ content: Search, shortcut: ⌘K }} / // 自定义位置 PromptInputButton tooltip{{ content: Search, side: bottom }} /PromptInputSelect系列模型下拉Trigger / Content / Item / Value 全套提交按钮PromptInputSubmit根据statussubmitted / streaming / error自动切换图标表单级能力onSubmit收到PromptInputMessage含text与files、accept/multiple/maxFiles/maxFileSize约束、globalDrop全文档拖拽、syncHiddenInput原生表单隐藏输入同步。PromptInput还提供状态管理 hooksconst attachments usePromptInputAttachments(); attachments.files; // 当前附件数组 attachments.add(files); // 添加文件 attachments.remove(id); // 按 ID 移除 attachments.clear(); // 清空 attachments.openFileDialog(); // 打开文件选择对话框当需要把输入状态提升到组件外部统一控制时使用可选的PromptInputProvider配合usePromptInputController/useProviderAttachments/usePromptInputReferencedSources在任意子组件中访问文本输入与附件状态完整 hooks 与属性表见 prompt-input.md本地实现见 prompt-input.tsx。Tool工具调用展示Tool组件专为 AI SDK 的ToolUIPart设计用可折叠面板展示工具调用的输入、输出、状态与错误Tool defaultOpen{true} ToolHeader typetool-fetch_weather_data state{weatherTool.state} / ToolContent ToolInput input{weatherTool.input} / ToolOutput output{MessageResponse{formatWeatherResult(weatherTool.output)}/MessageResponse} errorText{weatherTool.errorText} / /ToolContent /ToolToolHeader根据state自动渲染状态徽标getStatusBadge工具函数支持的状态包括input-streamingPending、input-availableRunning、approval-requestedAwaiting Approval、approval-respondedResponded、output-availableCompleted、output-errorError、output-deniedDeniedToolInput以带语法高亮的 JSON 展示参数ToolOutput展示执行结果或errorText错误信息完成/出错状态默认展开以呈现结果类型导出ToolPart ToolUIPart | DynamicToolUIPart覆盖静态与动态两种工具 UI 数据。后端示例使用 AI SDK 的streamText声明带 Zod 参数校验的工具并toUIMessageStreamResponse()流式返回前端即可无缝渲染完整示例见 tool.md本地实现见 tool.tsx。Reasoning流式推理展示Reasoning组件展示模型的思考过程流式期间自动展开、结束后自动收起Reasoning classNamew-full isStreaming{isReasoningStreaming} ReasoningTrigger / ReasoningContent{reasoningText}/ReasoningContent /ReasoningisStreaming为 true 时自动打开并显示脉冲动画指示器ReasoningTrigger自定义思考文案可通过getThinkingMessage(isStreaming, duration)定制ReasoningContent推理文本经 Streamdown 渲染useReasoning()子组件访问{ isStreaming, isOpen, setIsOpen, duration }上下文。适用于 Deepseek R1、Claude extended thinking 等以连续块输出思考内容的模型。如果模型输出的是离散、带标签的步骤如搜索查询、工具调用官方建议改用 Chain of Thought 组件做结构化展示。后端启用推理流需要显式开启result.toUIMessageStreamResponse({ sendReasoning: true })。Attachments / CodeBlock / Terminal高频场景组件Attachments统一展示图片、视频、音频、文档与来源文件。三种形态variantgrid消息内缩略图网格、inline输入区紧凑徽标 悬停预览、list带元数据的文件列表。辅助函数getMediaCategory(data)返回image | video | audio | document | source | unknowngetAttachmentLabel(data)返回展示名。删除按钮onRemove回调与AttachmentRemove组件配套见 attachments.md。CodeBlockShiki 语法高亮可选行号头部可组合CodeBlockTitle图标 文件名与CodeBlockActionsCodeBlockCopyButton复制成功态默认 2000ms支持CodeBlockLanguageSelector多语言切换与dark类深色模式。底层CodeBlockContainer使用contentVisibility做渲染性能优化。Terminal流式终端输出ansi-to-react解析 ANSI 颜色256 色、粗体、斜体、下划线内置流式光标动画、自动滚动、复制与清空按钮见 terminal.md。可扩展性AI Elements 的设计原则是组件尽可能透传原生属性。例如Message继承HTMLAttributesHTMLDivElement凡是div支持的属性className、onClick、id、ARIA 属性等都可以直接传入Tool透传Collapsible的 propsConversationScrollButton透传 shadcn/uiButton的 props。这意味着你可以用className叠加 Tailwind 类做样式微调用受控 props如Reasoning的open/onOpenChange接管内部状态用componentsMessageResponse或 render propConversation的children注入自定义渲染逻辑在组件之上包一层业务组件组合出符合自己产品的交互。定制化安装完成后无需额外配置即可使用——组件的 Tailwind 样式与脚本已随安装集成。若需要改样式直接编辑组件源码即可。以技能文档中的示例为例去掉MessageContent的圆角打开components/ai-elements/message.tsx移除根元素上的rounded-lg类export const MessageContent ({ children, className, ...props }: MessageContentProps) ( div className{cn( flex flex-col gap-2 text-sm text-foreground, group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground group-[.is-user]:px-4 group-[.is-user]:py-3, className, )} {...props} div classNameis-user:dark{children}/div /div );其中cn(...)会把传入的className与内置类合并Tailwind 的同名类冲突时以传入为准。由于组件就在项目源码中任何修改即时生效这是「组件即源码」模型的核心价值。故障排查Troubleshooting技能文档针对高频问题给出了明确排查路径组件没有样式确认项目已按 shadcn/uiTailwind 4规范配置——globals.css导入了 Tailwind 并包含 shadcn/ui 基础样式。运行 CLI 后项目没有任何新增文件逐项检查当前工作目录是项目根目录存在package.json的位置components.jsonshadcn 风格配置设置正确使用最新版本的 CLInpx ai-elementslatest主题切换失效应用一直停留在浅色模式确保应用使用 shadcn/ui 与 AI Elements 期望的同一套data-theme系统。默认实现会在html元素上切换data-theme属性同时tailwind.config.js需使用 class 或 data 选择器。组件导入报 module not found先确认文件确实存在若存在检查tsconfig.json是否配置了/路径别名{ compilerOptions: { baseUrl: ., paths: { /*: [./*] } } }AI 编程助手无法访问 AI Elements 组件依次验证配置文件语法是否为合法 JSON、文件路径是否与 AI 工具配置一致、修改后是否重启了编程助手、网络连接是否稳定。结语AI Elements 以「组件即源码」的方式把 AI 聊天界面中最复杂、最容易做丑的部分流式 Markdown、工具调用状态、附件管理、吸底滚动、模型选择封装为开箱即用的可组合组件。在 ZCode 仓库中这套组件已经完成本地化整合见 packages/ui/src/components/ai-elements/并针对中文渲染、ESM 解析、任务切换动画等真实工程问题做了适配改造是研究其源码实现、学习如何在生产级 AI 工作台中落地 AI 聊天 UI 的最佳参考。无论你是要快速搭一个聊天 Demo还是要构建完整的 AI 助手产品界面都可以从本仓库的技能文档SKILL.md与其 references 组件文档 出发按需安装、自由定制。赞分享人工智能大模型代码智能体AI Agent桌面应用后端前端CLI【免费下载链接】ZCodeZCode 是 AI 编程工作台提供桌面应用、浏览器界面和终端 Agent。本仓库包含客户端、后端服务、共享 UI以及 Agent CLI 与运行时源码。项目地址https://gitcode.com/zai-org/ZCode点击查看免费下载相关推荐在 ZCode 中构建 AI 聊天界面ai-elements Conversation 组件完整指南在 ZCode 中构建 AI 聊天界面ai elements Conversation 组件完整指南 Conversation 是 ZCode 仓库内置的 a人工智能大模型代码智能体AI Agent桌面应用后端前端CLI插件系统ZCode 集成指南使用 AI Elements Conversation 组件构建自动吸底的 AI 聊天界面ZCode 集成指南使用 AI Elements Conversation 组件构建自动吸底的 AI 聊天界面 导读 本指南以 ZCode 仓库内 .agenZCode 中构建 AI 聊天界面AI Elements 组件库安装、组合与深度定制实战指南ZCode 中构建 AI 聊天界面AI Elements 组件库安装、组合与深度定制实战指南 本文以 ZCode 仓库内嵌的 ai elements 技能文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表