| 能力 | 说明 |
|---|---|
| 对话界面 | Bubble、MessageList、ConversationList 组合出完整 Chat UI |
| 输入体验 | Sender 支持受控输入、发送、取消、前缀操作和模型切换入口 |
| 流式生成 | useStream、mockStream 和 Markdown streaming 状态适配流式回复 |
| 富文本输出 | Mark、CodeHighlighter 支持 Markdown、GFM、代码块和语法高亮 |
| Agent 过程 | Think、Thought、Citation 展示思考过程、步骤和引用来源 |
| 会话管理 | ConversationList、ConversationItem 支持搜索、折叠、收藏、置顶和删除 |
| 主题系统 | 基于 data-theme 和 CSS Variables,内置 light / dark 主题和柔和切换动画 |
| AI Ready | 在线 Demo 已接入真实 AI,优先通过 Vercel /api/chat 服务端代理请求模型 |
pnpm add @oakkles/llm-ui-react也可以使用 npm:
npm install @oakkles/llm-ui-react导入组件和样式:
import { ConfigProvider, MessageList, Sender } from '@oakkles/llm-ui-react'
import '@oakkles/llm-ui-react/style.css'
const messages = [
{
id: 'hello-user',
role: 'user',
content: '帮我总结今天的发布风险。',
},
{
id: 'hello-assistant',
role: 'assistant',
content: '可以从接口稳定性、文档一致性和回归覆盖三个方向拆分。',
},
] as const
export function Chat() {
return (
<ConfigProvider theme={{ mode: 'light' }} locale="zh-CN">
<MessageList messages={messages} />
<Sender onSend={(message) => console.log(message)} />
</ConfigProvider>
)
}当前 Storybook 已部署到 Vercel:
https://llm-ui-react.vercel.app其中 Examples / AI Conversation Demo / Default 已接入真实 AI:
浏览器 Demo
-> fetch('/api/chat')
-> Vercel Serverless Function
-> OpenAI-compatible 模型服务Mocked story 保留本地模拟流式回复,用于稳定的 Storybook interaction / browser tests。
Storybook 的全局 Light / Dark toolbar、左侧 manager、顶部工具栏和组件展示区会保持主题同步;Demo 内部的主题按钮也会反向同步 Storybook 全局主题。
此项目在开发过程中使用 Claude Code CLI 接入 gpt-5.5,核心实现围绕当前代码的结构、Storybook 反馈和本地验证闭环推进。
| 环节 | 使用方式 |
|---|---|
| 需求拆解 | 通过 Plan 模式先梳理实现边界、关键文件、风险点和验证方式,再进入编码 |
| CLAUDE.md | 通过 /init 初始化项目级 memory 到 CLAUDE.md,规范组件开发流程 |
| 代码检索 | 使用 Explore subagent 搜索组件、hooks、构建配置和 Storybook 相关实现 |
| 组件设计 | 使用 component-design-researcher subagent 对比 shadcn/ui、assistant-ui、Ant Design X 等 AI UI 组件模式 |
| 视觉与文档 | 使用 frontend-design、readme-polish skills 辅助 Demo 和视觉表达优化 |
| MCP 辅助 | 结合 shadcn / assistant-ui 文档 MCP 获取组件 API、示例和设计参考,避免只凭记忆实现 |
| 安全边界 | 真实模型密钥只放在 Vercel 服务端环境变量;README、源码和 Storybook 中只保留占位变量 |
| 代码 Review | 修改后通过 git diff 逐项检查变更,重点看 API 设计、类型约束、主题同步、密钥暴露风险和 Storybook 交互稳定性 |
| 验证闭环 | 使用 pnpm lint、pnpm build、pnpm test:storybook、pnpm build-storybook 和线上 Vercel Demo 检查关键路径 |
AI 主要负责扩大检索范围、给出实现计划、辅助生成样板代码和发现遗漏;最终合入前仍以项目实际代码、lint/build/test 结果和浏览器中的 Storybook 表现为准。
D:\LLM-UI
├── api/ # Vercel Serverless Functions
│ └── chat.ts # 同源 AI 流式代理接口
├── assets/ # README 与文档静态资源
├── .storybook/ # Storybook 配置、主题同步和预览样式
│ ├── main.ts
│ ├── manager.ts
│ ├── preview.ts
│ └── preview.css
├── src/
│ ├── components/ # Primitive + Styled 组件实现与 stories
│ │ ├── actions/
│ │ ├── bubble/
│ │ ├── citation/
│ │ ├── code-highlighter/
│ │ ├── config-provider/
│ │ ├── conversation/
│ │ ├── demo/
│ │ ├── mark/
│ │ ├── message-list/
│ │ ├── notification/
│ │ ├── prompts/
│ │ ├── sender/
│ │ ├── think/
│ │ └── thought/
│ ├── hooks/ # 组件库 hooks
│ ├── locale/ # 多语言文案
│ ├── styles/ # tokens、light / dark 主题变量
│ ├── types/ # 公共类型
│ ├── utils/ # className、stream、Markdown 等工具
│ ├── index.ts # 组件库入口
│ ├── index.css # 全量组件样式入口
│ └── style.ts # CSS 构建入口
├── dist/ # npm 发布产物
├── storybook-static/ # Storybook 静态构建产物
├── tsup.config.ts # JS / DTS 构建配置
├── vite.config.ts # 开发与测试配置
├── vite.styles.config.ts # 样式构建配置
└── package.jsonflowchart TD
A[用户在 Sender 输入问题] --> B[按 Enter 或点击发送]
B --> C[AIConversationDemo.handleSend]
C --> D[创建 user message]
C --> E[创建 assistant 占位 message loading=true]
D --> F[更新 messagesByConversation]
E --> F
F --> G[MessageList 重新渲染]
G --> H[页面出现用户消息和思考中的 assistant 气泡]
C --> I[整理历史消息 createAIHistory]
I --> J[createAIResponseStreamWithReasoning]
J --> K[fetch POST /api/chat]
K --> L[Vercel Serverless api/chat.ts]
L --> M[读取环境变量 DEEPSEEK_API_KEY]
M --> N[请求 DeepSeek /chat/completions stream=true]
N --> O[DeepSeek 返回 OpenAI-style SSE]
O --> P[api/chat.ts 解析 delta]
P --> Q{delta 类型}
Q -->|reasoning_content| R[写出 data: type=reasoning]
Q -->|content| S[写出 data: type=content]
Q -->|DONE| T[写出 data: type=done]
R --> U[前端 processSSEStream 解析]
S --> U
T --> U
U --> V{chunk.type}
V -->|reasoning| W[onReasoning 更新 reasoningStore]
V -->|content| X[onContent 更新 assistant message content]
V -->|done| Y[onComplete 收尾 loading=false]
W --> Z[Think / Thought 展示推理过程]
X --> AA[Mark 渲染 Markdown 正文]
Y --> AB[Notification 提示回复完成]
推荐把模型 API Key 只放在 Vercel 服务端环境变量中,前端只调用同源后端接口:
DEEPSEEK_API_KEY=your-server-side-key
DEEPSEEK_MODEL=deepseek-chat前端请求示例:
async function* requestAI(message: string) {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message }),
})
const reader = response.body?.getReader()
const decoder = new TextDecoder()
if (!reader) return
while (true) {
const { done, value } = await reader.read()
if (done) break
yield decoder.decode(value)
}
}当前 Demo 还提供浏览器直连 DeepSeek 的兜底路径:当 /api/chat 不可用或未配置时,可通过 VITE_DEEPSEEK_API_KEY 和 VITE_DEEPSEEK_MODEL 在静态 Storybook 中直接请求模型。
VITE_DEEPSEEK_API_KEY=your-browser-visible-key
VITE_DEEPSEEK_MODEL=deepseek-chat注意:VITE_* 变量会进入前端构建产物,任何访问页面的人都能在浏览器 DevTools 中看到这个 key。生产环境更推荐使用 /api/chat 服务端代理。
| 分类 | 组件 |
|---|---|
| 基础上下文 | ConfigProvider |
| 消息展示 | Bubble、MessageList |
| 输入与发送 | Sender |
| Markdown 与代码 | Mark、CodeHighlighter |
| 会话管理 | ConversationList、ConversationItem |
| 快捷操作 | Prompts、Actions |
| 推理与引用 | Think、Thought、Citation |
| 通知反馈 | Notification、NotificationStack |
| API | 用途 |
|---|---|
useConfig |
读取全局配置 |
useLocale |
读取当前语言包 |
useTheme |
读取和切换主题 |
useStream |
管理流式文本状态 |
useVirtualList |
虚拟列表能力 |
mockStream |
本地模拟流式输出 |
streamToGenerator |
将 Web Stream 转为 async generator |
generatorToStream |
将 async generator 转为 Web Stream |
sanitizeMarkdown |
修复 streaming 阶段不完整 Markdown |
主题通过 data-theme 属性和 CSS Variables 驱动:
document.documentElement.setAttribute('data-theme', 'dark')也可以通过 ConfigProvider 和 useTheme 控制:
<ConfigProvider theme={{ mode: 'dark' }} locale="zh-CN">
<App />
</ConfigProvider>内置主题文件:
src/styles/themes/light.css
src/styles/themes/dark.css
src/styles/tokens.css所有变量都使用 --llm- 前缀,便于外部覆盖。
pnpm install
pnpm storybook常用命令:
pnpm lint # ESLint 检查
pnpm build # 构建库代码、类型声明和 CSS
pnpm test:storybook # 运行 Storybook browser tests
pnpm build-storybook # 构建 Storybook 静态站点库构建输出到 dist/:
dist/index.js # ESM
dist/index.cjs # CommonJS
dist/index.d.ts # 类型声明
dist/style.css # 组件样式用户应同时导入组件入口和样式入口:
import { Bubble } from '@oakkles/llm-ui-react'
import '@oakkles/llm-ui-react/style.css'