Skip to content

Latest commit

 

History

48 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LLM UI logo

@oakkles/llm-ui-react

面向 AI / LLM 产品的 React 组件库,用一套可组合组件快速搭建 Chat、Agent、知识库问答和流式生成界面。

npm version React 18+ TypeScript ready Storybook docs Package format License

在线 Storybook / Vercel Demo

特性

能力 说明
对话界面 BubbleMessageListConversationList 组合出完整 Chat UI
输入体验 Sender 支持受控输入、发送、取消、前缀操作和模型切换入口
流式生成 useStreammockStream 和 Markdown streaming 状态适配流式回复
富文本输出 MarkCodeHighlighter 支持 Markdown、GFM、代码块和语法高亮
Agent 过程 ThinkThoughtCitation 展示思考过程、步骤和引用来源
会话管理 ConversationListConversationItem 支持搜索、折叠、收藏、置顶和删除
主题系统 基于 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>
  )
}

在线 Demo

当前 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 全局主题。

AI 协作开发流程

此项目在开发过程中使用 Claude Code CLI 接入 gpt-5.5,核心实现围绕当前代码的结构、Storybook 反馈和本地验证闭环推进。

环节 使用方式
需求拆解 通过 Plan 模式先梳理实现边界、关键文件、风险点和验证方式,再进入编码
CLAUDE.md 通过 /init 初始化项目级 memoryCLAUDE.md,规范组件开发流程
代码检索 使用 Explore subagent 搜索组件、hooks、构建配置和 Storybook 相关实现
组件设计 使用 component-design-researcher subagent 对比 shadcn/ui、assistant-ui、Ant Design X 等 AI UI 组件模式
视觉与文档 使用 frontend-designreadme-polish skills 辅助 Demo 和视觉表达优化
MCP 辅助 结合 shadcn / assistant-ui 文档 MCP 获取组件 API、示例和设计参考,避免只凭记忆实现
安全边界 真实模型密钥只放在 Vercel 服务端环境变量;README、源码和 Storybook 中只保留占位变量
代码 Review 修改后通过 git diff 逐项检查变更,重点看 API 设计、类型约束、主题同步、密钥暴露风险和 Storybook 交互稳定性
验证闭环 使用 pnpm lintpnpm buildpnpm test:storybookpnpm 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.json

真实 AI 接入

flowchart 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 提示回复完成]
Loading

推荐把模型 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_KEYVITE_DEEPSEEK_MODEL 在静态 Storybook 中直接请求模型。

VITE_DEEPSEEK_API_KEY=your-browser-visible-key
VITE_DEEPSEEK_MODEL=deepseek-chat

注意:VITE_* 变量会进入前端构建产物,任何访问页面的人都能在浏览器 DevTools 中看到这个 key。生产环境更推荐使用 /api/chat 服务端代理。

组件矩阵

分类 组件
基础上下文 ConfigProvider
消息展示 BubbleMessageList
输入与发送 Sender
Markdown 与代码 MarkCodeHighlighter
会话管理 ConversationListConversationItem
快捷操作 PromptsActions
推理与引用 ThinkThoughtCitation
通知反馈 NotificationNotificationStack

Hooks 与工具

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')

也可以通过 ConfigProvideruseTheme 控制:

<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'

About

Typescript/React Library 一个大模型对话组件库

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages