autogenui
v1.0.12
Published
AI Assistant UI 通用工具包(公共版)
Maintainers
Readme
autogenui
AI 对话 UI 组件库,支持流式输出、思考过程展示、AutoUI/Page 渲染,可配置后端 API,适用于 React 项目。
npm 包名:autogenui(npmjs.com)
功能
- 流式输出:SSE / NDJSON 解析,逐 chunk 更新
- 思考过程:支持
event: thinking/event: data或「完整回复」分隔符 - AutoUI / Page:表格、卡片、轮播、图表、页面等 JSON 配置渲染
- 纯文字:后端只返回文字时也会正常展示
- 复制 / 重新生成:仅在流式结束后显示
- 可配置 API(apiConfig)或自定义 onSend
安装
npm install autogenui- 适用:React 项目(Next.js、Vite、CRA 等)
- 不适用:Vue / Angular / Svelte(组件为 React 实现)
- 依赖:
react、react-dom、lucide-react(peer)
使用手顺(3 步)
| 步骤 | 操作 |
|------|------|
| 1 | npm install autogenui |
| 2 | 入口文件加一行:import 'autogenui/style'; |
| 3 | 页面中:import { ChatUI } from 'autogenui';,使用 <ChatUI apiConfig={{ apiBaseUrl: '后端地址', chatPath: '/api/chat', stream: true }} /> |
Next.js 若报 Can't resolve 'autogenui',在 next.config.mjs 中加 transpilePackages: ['autogenui']。
使用示例
使用 apiConfig(推荐)
import { ChatUI } from 'autogenui';
<ChatUI
apiConfig={{
apiBaseUrl: 'http://localhost:8080',
chatPath: '/api/chat',
stream: true,
thinkingSeparator: '完整回复',
}}
placeholder="输入消息…"
/>自定义 onSend
<ChatUI
onSend={async (query) => {
const res = await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ messages: [{ content: query }] }) });
if (!res.body) return (await res.text()) ?? '';
return (async function* () {
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
yield decoder.decode(value, { stream: true });
}
})();
}}
/>仅用输入框与消息气泡
import { ChatInput, ChatMessageBubble } from 'autogenui';
import type { ChatMessage } from 'autogenui';
const [messages, setMessages] = useState<ChatMessage[]>([]);
<>
{messages.map((m) => <ChatMessageBubble key={m.id} message={m} />)}
<ChatInput onSend={...} isLoading={...} />
</>常用 props 示例
<ChatUI
apiConfig={{ apiBaseUrl: 'http://localhost:8080', chatPath: '/api/chat', stream: true }}
sendHistory={false} // 不带历史,只发当前输入(默认 true 会带历史)
enableHistory
storageKey="my-app:chat"
greetingTitle="Hi,我是你的AI助手"
greetingSubtitle="使用 npm 包 autogenui + 独立 CSS 测试"
placeholder="输入消息…"
/>| 属性 | 说明 |
|------|------|
| sendHistory | 是否把历史对话一并发给接口;false 时只发当前输入,请求体里 messages 仅一条 |
| greetingTitle | 无消息时居中大标题 |
| greetingSubtitle | 无消息时居中副标题 |
| placeholder | 输入框占位文案 |
| storageKey | 开启 enableHistory 时,历史会话在 localStorage 的 key |
样式
推荐:使用包内独立 CSS,无需配置 Tailwind。
在应用入口引入一次:
import 'autogenui/style';
// 或
import 'autogenui/dist/autogenui.css';可选:若希望与宿主 Tailwind 主题统一,可将 ./node_modules/autogenui/src/**/*.{js,ts,jsx,tsx} 加入 Tailwind 的 content,并在 theme.extend.colors 中配置 primary。暗色模式需在根节点加 class="dark"。
流式接口 API 要求(后端对接)
前端通过 apiConfig.apiBaseUrl + apiConfig.chatPath 请求你的接口,后端需满足以下约定。
请求
| 项目 | 要求 |
|------|------|
| 方法 | POST |
| 请求头 | 至少 Content-Type: application/json;可透传 apiConfig.headers(如 Authorization) |
| 请求体(JSON) | 见下表 |
请求体参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| messages | Array<{ content: string }> | 是 | 历史 + 当前用户消息,每条仅需 content,不需 role |
| stream | boolean | 否 | 前端默认传 true,表示要流式响应 |
其他项目若需要额外参数(如 model、temperature、user 等),通过 apiConfig.extraBody 传入,会与 messages、stream 一并合并进请求体,后端按需解析。示例见下。
请求体示例(仅 messages + stream):
{
"messages": [
{ "content": "你好" },
{ "content": "我是上一条回复" },
{ "content": "请再介绍一下自己" }
],
"stream": true
}带额外参数时(在业务里配置 extraBody,最终请求体会合并这些字段):
<ChatUI
apiConfig={{
apiBaseUrl: 'http://localhost:8080',
chatPath: '/api/chat',
stream: true,
extraBody: { model: 'gpt-4', temperature: 0.7, user: 'user-123' },
}}
/>此时请求体除 messages、stream 外还会包含 model、temperature、user。
响应
| 项目 | 要求 |
|------|------|
| 状态码 | 成功为 200 |
| 响应头 | Content-Type: text/event-stream(SSE 流式) |
| 响应体 | 标准 SSE:多行文本,每段为 event: 行 + data: 行(或仅 data: 行) |
SSE 格式:event 与 data 是两行,不是一行里两个字段。
- 思考过程(可选):先发
event: thinking,下一行data: 思考内容,可多条。 - 正文内容:发
event: data,下一行data: 正文片段,可多条。 - 结束:可发空行或
data: [DONE],或直接关闭流。
前端会从 data 行取内容展示;若 data 行为 JSON,会尝试取 choices[0].delta.content、content、text 等字段。
响应示例(SSE 片段):
event: thinking
data: 让我先想想…
event: data
data: 你好,我是 AI 助手。
event: data
data: 有什么可以帮你的?小结
- 请求:
POST+ JSON 体,必填messages(仅含content),建议带stream: true。 - 响应:
Content-Type: text/event-stream,按 SSE 发 event 行 + data 行;思考用event: thinking,正文用event: data。
apiConfig 说明
| 字段 | 说明 |
|------|------|
| apiBaseUrl | 接口基础 URL |
| chatPath | 聊天路径,默认 /v1/chat/completions |
| stream | 是否流式,默认 true |
| headers | 额外请求头 |
| extraBody | 请求体额外参数(与 messages、stream 合并后发给后端) |
| thinkingSeparator | 思考与正文分隔符,如 "完整回复" |
messages 与请求体类型定义位置:在包内 src/api.ts。ChatRequestMessage 为 { content: string },ChatRequestBody 为 { messages: ChatRequestMessage[]; stream?: boolean; [key: string]: unknown }。如需在 TypeScript 中引用,可从包入口导入:import type { ChatRequestMessage, ChatRequestBody } from 'autogenui'。
扩展方案:历史记录 API 与快捷问题 API
以下为可选扩展的设计方案,便于后续在包内或宿主项目中接入。
一、历史记录 API(historyApiConfig)
现状:已有 historyApiConfig 类型与 paths 占位;当前仅用 localStorage + onConversationsChange 由宿主自行同步。
建议后端约定(若提供历史记录服务):
| 能力 | 方法 | 路径示例 | 请求 | 响应 |
|------|------|----------|------|------|
| 会话列表 | GET | /api/chat/conversations | - | { list: Array<{ id, title, updatedAt, lastReadAt? }> } |
| 单条会话+消息 | GET | /api/chat/conversations/:id | - | { id, title, updatedAt, messages: Array<{ id, role, content, ... }> } |
| 创建会话 | POST | /api/chat/conversations | { title?: string } | { id, title, updatedAt } |
| 更新会话 | PATCH | /api/chat/conversations/:id | { title?: string } | 同单条 |
| 删除会话 | DELETE | /api/chat/conversations/:id | - | 204 |
| 保存消息 | POST | /api/chat/conversations/:id/messages | { messages: Array<{ role, content }> } | 200 |
前端接入方式(二选一或组合):
- 仅同步:不配
historyApiConfig,继续用storageKey+onConversationsChange,在回调里把conversations发到自家后端(现有做法)。 - 全走后端:配置
historyApiConfig.baseUrl+historyApiConfig.paths,在包内实现:进入页面时 GET 列表并设initialConversations;切换/新建/删除时调对应接口;每次消息变更时 POST 保存消息。实现时需在 ChatUI 内根据historyApiConfig有则请求、无则仅本地。
类型:保持现有 ChatHistoryApiConfig(baseUrl、headers、paths),按上表实现即可。
二、快捷问题 / 初始推荐问题 API
目的:在无消息时(首屏)展示若干可点击的推荐问题,点击后作为用户输入发送。
方案 A:静态配置(推荐先做)
- 新增 props:
quickQuestions?: string[]。 - 当
messages.length === 0时,在greetingSubtitle下方渲染一组按钮/芯片,文案为数组项,点击即把该字符串作为用户输入触发发送。 - 无需后端,适合固定话术或从构建时配置注入。
方案 B:接口拉取
- 新增配置:
quickQuestionsApi?: { url: string; method?: 'GET'; headers?: Record<string, string> },或回调loadQuickQuestions?: () => Promise<string[]>。 - 进入无消息状态时请求一次,将返回的字符串数组当作「快捷问题」渲染;失败则隐藏或回退为空/静态列表。
- 适合按用户、场景或配置动态下发话术。
建议:先支持方案 A(quickQuestions 数组),再按需在包内或宿主项目里用 useEffect + fetch 封装方案 B(或宿主自己请求后把结果通过 quickQuestions 传入)。
三、小结
| 能力 | 建议 | 说明 |
|------|------|------|
| 历史记录 | 保持 onConversationsChange;可选实现 historyApiConfig 的请求逻辑 | 后端按上表提供 REST 即可对接 |
| 快捷问题 | 先加 quickQuestions?: string[],空状态渲染可点击项并触发发送 | 后续可加 loadQuickQuestions 或 URL 配置做动态拉取 |
发布到 npm
当前包已发布到 npm 官方(公开)。更新版本后发布:
- 修改
package.json的version(如 1.0.2) npm run buildnpm publish --access public(若启用 2FA,加--otp=六位验证码)
项目结构
src/
├── index.ts
├── types.ts
├── parse-json.ts
├── api.ts
├── ChatUI.tsx
├── ChatInput.tsx
├── ChatMessage.tsx
├── auto-ui-renderer.tsx
├── page-renderer.tsx
├── autogenui.css # Tailwind 入口,构建为 dist/autogenui.css
├── table.tsx, card.tsx, carousel.tsx, line-chart.tsx
└── components/License
MIT
