首页/新闻资讯/正文详情

ZCode 中的 Sources 组件:为 AI 对话响应构建可折叠引用来源展示

发布时间:2026/9/23 7:24:57 来源:云帆数科 栏目:资讯中心
ZCode 中的 Sources 组件:为 AI 对话响应构建可折叠引用来源展示
【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址https://gitcode.com/gh_mirrors/zco/ZCode点击查看免费下载导读本文以 ZCode 仓库内置的ai-elements技能中Sources组件的完整参考文档.agents/skills/ai-elements/references/sources.md为核心系统讲解如何在基于 AI SDK 的聊天应用中为模型生成的回答展示来源与引用citations。文章将覆盖Sources、SourcesTrigger、SourcesContent、Source四个组件的安装方式、与 Perplexity 等搜索型模型的端到端接入示例、全部 Props 参数表并结合 ZCode 仓库中的实际实现源码packages/ui/src/components/ai-elements/sources.tsx深入剖析其折叠交互原理与自定义渲染方法帮助你快速在自己的 AI 前端中落地引用来源这一关键可信度功能。什么是 Sources 组件Sources是一个允许用户查看生成回答时所使用来源或引用的 UI 组件。在基于检索增强或联网搜索的 AI 应用中模型会引用多个网页、文档作为回答依据Sources组件将这些来源以可折叠collapsible的形式组织起来默认只显示一个触发按钮例如Used N sources用户点击后展开来源列表每条来源以带图标的超链接形式展示。从 ZCode 仓库的实现看packages/ui/src/components/ai-elements/sources.tsx该组件由四个协作的部分组成底层依赖 radix-ui 的Collapsible原语见 packages/ui/src/components/ui/collapsible.tsx组件职责Sources折叠容器根节点内部渲染Collapsible持有展开/收起状态SourcesTrigger折叠触发器显示来源数量默认文案Used N sources与箭头图标SourcesContent折叠内容区承载来源列表带展开/收起动画Source单个来源链接默认渲染书本图标 标题新标签页打开四个组件均支持通过className与展开的 props 深度定制这与该技能目录.agents/skills/ai-elements/SKILL.md所倡导的尽可能透传原生属性的扩展性原则一致。安装在具备以下前置条件的项目中通过 AI Elements CLI 即可一键安装Sources组件Node.js 18 及以上版本已安装 AI SDK 的 Next.js 项目已安装 shadcn/ui未安装时执行安装命令会自动补装。安装命令npx ai-elementslatest add sources如果你的项目使用 pnpm 或 bun 作为包管理器请使用对应的运行器pnpm dlx ai-elementslatest或bunx --bun ai-elementslatest。CLI 会将组件代码及其依赖写入你项目中 shadcn 配置的组件目录默认位置是/components/ai-elements/因此安装完成后代码中引入路径即为import { Source, Sources, SourcesContent, SourcesTrigger } from /components/ai-elements/sources;组件代码会作为你项目源码的一部分落地而非封装在不可见的库里这意味你可以直接打开组件文件查看实现、按需修改样式与逻辑。若引入时报module not found请检查tsconfig.json中是否配置了/路径别名{ compilerOptions: { baseUrl: ., paths: { /*: [./*] } } }与 AI SDK 集成构建一个联网搜索问答示例参考文档给出了一个完整的实战示例对应的示例源码位于 .agents/skills/ai-elements/scripts/sources.tsx使用 Perplexity Sonar 模型构建一个简单的网页搜索 Agent前端展示每次回复引用的来源。前端组件app/page.tsxuse client; import { useChat } from ai-sdk/react; import { Source, Sources, SourcesContent, SourcesTrigger } from /components/ai-elements/sources; import { PromptInput, type PromptInputMessage, PromptInputTextarea, PromptInputSubmit, } from /components/ai-elements/prompt-input; import { Conversation, ConversationContent, ConversationScrollButton, } from /components/ai-elements/conversation; import { Message, MessageContent, MessageResponse } from /components/ai-elements/message; import { useState } from react; import { DefaultChatTransport } from ai; const SourceDemo () { const [input, setInput] useState(); const { messages, sendMessage, status } useChat({ transport: new DefaultChatTransport({ api: /api/sources, }), }); const handleSubmit (message: PromptInputMessage) { if (message.text.trim()) { sendMessage({ text: message.text }); setInput(); } }; return ( div classNamemax-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px] div classNameflex flex-col h-full div classNameflex-1 overflow-auto mb-4 Conversation ConversationContent {messages.map((message) ( div key{message.id} {message.role assistant ( Sources SourcesTrigger count{message.parts.filter((part) part.type source-url).length} / {message.parts.map((part, i) { switch (part.type) { case source-url: return ( SourcesContent key{${message.id}-${i}} Source key{${message.id}-${i}} href{part.url} title{part.url} / /SourcesContent ); } })} /Sources )} Message from{message.role} key{message.id} MessageContent {message.parts.map((part, i) { switch (part.type) { case text: return ( MessageResponse key{${message.id}-${i}} {part.text} /MessageResponse ); default: return null; } })} /MessageContent /Message /div ))} /ConversationContent ConversationScrollButton / /Conversation /div PromptInput onSubmit{handleSubmit} classNamemt-4 w-full max-w-2xl mx-auto relative PromptInputTextarea value{input} placeholderAsk a question and search the... onChange{(e) setInput(e.currentTarget.value)} classNamepr-12 / PromptInputSubmit status{status streaming ? streaming : ready} disabled{!input.trim()} classNameabsolute bottom-1 right-1 / /PromptInput /div /div ); }; export default SourceDemo;这段代码的关键逻辑在于通过useChat拿到流式消息后对message.parts中type source-url的 part 逐一映射为Source链接并用SourcesTrigger的count属性展示来源总数文本 part 则交给MessageResponse渲染。折叠容器Sources仅包裹 assistant 消息用户消息不展示来源。后端路由api/chat/route.tsimport { convertToModelMessages, streamText, UIMessage } from ai; import { perplexity } from ai-sdk/perplexity; // Allow streaming responses up to 30 seconds export const maxDuration 30; export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } await req.json(); const result streamText({ model: perplexity/sonar, system: You are a helpful assistant. Keep your responses short ( 100 words) unless you are asked for more details. ALWAYS USE SEARCH., messages: await convertToModelMessages(messages), }); return result.toUIMessageStreamResponse({ sendSources: true, }); }后端的关键配置是toUIMessageStreamResponse({ sendSources: true })开启后AI SDK 会把模型返回的引用来源编码为source-url类型的 UI message part前端据此驱动Sources组件渲染。系统提示词中的 ALWAYS USE SEARCH 用于引导 Sonar 模型始终执行搜索从而稳定地产出可展示的来源数据。maxDuration 30允许流式响应最长 30 秒。功能特性Sources组件围绕来源展示场景提供了以下能力可折叠组件用户可按需展开/收起回答所使用的来源或引用列表触发器与内容可定制SourcesTrigger与SourcesContent均可传入自定义子元素或样式支持自定义来源Source组件接受任意href与title可渲染任意来源/引证链接响应式设计布局适配移动端折叠动画与交互在窄屏下同样可用简洁现代的样式基于 Tailwind 与 shadcn/ui 主题体系可通过className无缝接入既有主题。自定义渲染SourcesTrigger与Source均支持 children 覆盖默认内容这为深度定制提供了入口。参考文档提供了自定义示例对应源码 .agents/skills/ai-elements/scripts/sources-custom.tsxuse client; import { Source, Sources, SourcesContent, SourcesTrigger } from /components/ai-elements/sources; import { ChevronDownIcon, ExternalLinkIcon } from lucide-react; const sources [ { href: https://stripe.com/docs/api, title: Stripe API Documentation }, { href: https://docs.github.com/en/rest, title: GitHub REST API }, { href: https://docs.aws.amazon.com/sdk-for-javascript/, title: AWS SDK for JavaScript, }, ]; const Example () ( div style{{ height: 110px }} Sources SourcesTrigger count{sources.length} p classNamefont-mediumUsing {sources.length} citations/p ChevronDownIcon classNamesize-4 / /SourcesTrigger SourcesContent {sources.map((source) ( Source href{source.href} key{source.href} {source.title} ExternalLinkIcon classNamesize-4 / /Source ))} /SourcesContent /Sources /div ); export default Example;与默认渲染相比自定义示例做了两处增强一是触发器文案改为 Using N citations 并显式放置下箭头图标二是每条来源追加ExternalLinkIcon外链图标语义上提示用户点击后将离开当前页面。这正是该组件可像自己写的代码一样自由修改的体现。结合源码看自定义的实现原理在 ZCode 的组件实现中packages/ui/src/components/ai-elements/sources.tsxSourcesTrigger使用{children ?? (...)}的写法传入 children 时完全渲染自定义内容未传入时才回退到默认的 Used {count} sources 文案与ChevronDownIconSource同样用{children ?? (...)}在无 children 时回退到BookIcontitle的默认布局。由此可推断任何自定义内容都是通过 children 覆盖实现的而组件自身仅负责折叠状态与基础 a 标签语义互不干扰。Props 参考以下是四个组件的完整 Props 说明与参考文档一致并结合实现源码补充类型来源。Sources /Prop类型默认值说明...propsReact.HTMLAttributesHTMLDivElement-其余所有 props 透传到根 div实现中Sources实际渲染为 radix-ui 的Collapsible根组件见 packages/ui/src/components/ui/collapsible.tsx因此defaultOpen、open、onOpenChange等折叠控制 props 同样可用。SourcesTrigger /Prop类型默认值说明countnumber必填触发器上展示的来源数量...propsReact.ComponentPropstypeof CollapsibleTrigger-其余 props 透传到 CollapsibleTrigger 组件SourcesContent /Prop类型默认值说明...propsReact.HTMLAttributesHTMLDivElement-其余 props 透传到内容容器实现中SourcesContent渲染为CollapsibleContent内置了data-[state]驱动的展开/收起动画类fade-out、slide-in-from-top 等实际生效样式可参考 packages/ui/src/components/ai-elements/sources.tsx。Source /Prop类型默认值说明...propsReact.AnchorHTMLAttributesHTMLAnchorElement-其余 props 透传到 a 元素Source即一个a锚点元素实现中默认带有target_blank与relnoreferrer保证来源在新标签页打开且不泄露来源页信息href、title等标准链接属性均可用。主题与样式注意事项Sources组件继承 shadcn/ui 的>赞分享【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址https://gitcode.com/gh_mirrors/zco/ZCode点击查看免费下载相关推荐如何用Ventoy打造终极多系统启动U盘告别反复格式化一U盘装遍所有操作系统如何用Ventoy打造终极多系统启动U盘告别反复格式化一U盘装遍所有操作系统 还在为每次重装系统都要重新制作启动盘而烦恼吗还在因为U盘只能存放一个系统镜像操作系统固件开发工具marimo Accordion 组件详解用 mo.accordion 构建可折叠内容区marimo Accordion 组件详解用 mo.accordion 构建可折叠内容区 导读 本文围绕 marimo 的 mo.accordion 布局组件数据科学前端后端AI 应用推荐开源项目React响应式折叠组件React Collapsible推荐开源项目React响应式折叠组件React Collapsible 在构建动态和交互式的网页应用时处理大量信息展示的高效性和条理性至关重要。今天我创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Ceph 离线 OSD 检修实战:ceph-objectstore-tool 对象级诊断与修复完全指南
Ceph 离线 OSD 检修实战:ceph-objectstore-tool 对象级诊断与修复完全指南

存储分布式文件系统对象存储后端高可用 【免费下载链接】ceph Ceph is a distributed object, block, and file storage platform 项目地址: https://gitcode.com/gh_mirrors/ce/ceph 点击查看 免费下载 ceph-objectstore-tool 是 Ceph 发行版中面向底层对象存储&… · 2026/9/23 7:24:51

秦国权力结构解析:宣太后与军功爵制的博弈
秦国权力结构解析:宣太后与军功爵制的博弈

1. 历史背景与核心问题解析公元前3世纪的秦国正处于崛起关键期,秦昭襄王在位期间(前306年-前251年)完成了对六国的战略压制。这段历史中,宣太后(芈八子)作为中国历史上首位临朝称制的女性统治者&#xff0c… · 2026/9/23 7:24:51

Yii2 行为(Behavior)机制完全指南:基于 framework 源码深入剖析注入、事件响应与实战
Yii2 行为(Behavior)机制完全指南:基于 framework 源码深入剖析注入、事件响应与实战

后端Web框架 【免费下载链接】yii2 Yii 2: The Fast, Secure and Professional PHP Framework 项目地址: https://gitcode.com/gh_mirrors/yi/yii2 点击查看 免费下载 导读:本文以 Yii2 官方指南《Comportements》(行为)章节为骨… · 2026/9/23 7:24:51

BurpsuitePro 2022.2安装配置实战:JDK17、代理与CA证书全攻略
BurpsuitePro 2022.2安装配置实战:JDK17、代理与CA证书全攻略

简介:Burpsuite专业版2022.2完整安装包,附带作者整理的安装配置教程,面向安全测试、渗透测试及Web抓包分析人员,解决专业版获取门槛高、环境配置繁琐的问题,初学者也能按步骤完成部署。压缩包共包含368个文件&#xff… · 2026/9/23 8:58:34

纸张大小配置踩坑全记录:5个高频报错与避坑指南
纸张大小配置踩坑全记录:5个高频报错与避坑指南

纸张大小配置踩坑全记录:5个高频报错与避坑指南 盯着屏幕上一行行红色的 StackTrace,是不是感觉脑子都要炸了?明明只是打印个报表,或者生成个 PDF 文档,代码逻辑看着没毛病,一运行就抛出… · 2026/9/23 8:58:34

1024流量红利实战:程序员节三大策略提前布局
1024流量红利实战:程序员节三大策略提前布局

1. 1024这个数字在IT圈到底意味着什么1024在计算机世界里是个绕不开的数字。1KB等于1024字节,1MB等于1024KB,1GB等于1024MB,整个存储体系都建立在这个2的10次方之上。对程序员来说,这个数字天然带着一种身份认同感。每年10月24日被… · 2026/9/23 8:58:34

C#动态编译技术:原理、实践与优化指南
C#动态编译技术:原理、实践与优化指南

1. 为什么我们需要动态编译执行?在传统开发模式中,每次业务逻辑变更都需要经历"修改代码→重新编译→部署上线"的完整流程。我曾在金融行业做过一个报表系统,客户每周都要新增计算规则,每次改动都意味着:开发… · 2026/9/23 8:58:34

Java课程设计项目拆解:用Swing和多线程实现黄金矿工游戏
Java课程设计项目拆解:用Swing和多线程实现黄金矿工游戏

简介:一份基于Java与GUI图形界面的黄金矿工小游戏课程设计资源,定位明确,主要面向刚接触Java或数据结构、需要完成课程大作业或练手项目的同学。压缩包共28个文件,体积仅1.35MB,其中包含5个Java源文件、7个class编译文… · 2026/9/23 8:58:34

OpenSpec实战:把API规范变成可校验、可生成代码的工程化体系
OpenSpec实战:把API规范变成可校验、可生成代码的工程化体系

"OpenSpec"这名字乍一听有点像某个学术标准组织,但放到日常开发语境里,它其实是一个特别实用的工具型项目:把散落在各处的 API 规范、数据模型、接口文档整合成一套可校验、可生成代码、可自动化检查的工程化体系。很多团队前期接口… · 2026/9/23 8:58:27

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码