可嵌入聊天组件
可嵌入聊天组件
相关源文件
本章引用的主要源码文件:
examples/widget/.env.exampleexamples/widget/.eslintrc.jsonexamples/widget/.gitignoreexamples/widget/README.mdexamples/widget/next.config.mjsexamples/widget/package-lock.jsonexamples/widget/package.jsonexamples/widget/postcss.config.mjsexamples/widget/src/app/globals.cssexamples/widget/src/app/layout.tsxexamples/widget/src/app/page.tsxexamples/widget/src/app/widget/Widget.tsxexamples/widget/tsconfig.json
可嵌入聊天组件提供了一种将 Onyx 的 AI 聊天能力集成到外部网站或内部门户的方式。代码库包含两种主要实现:一个框架无关的 Lit Web 组件(位于 widget/ 目录)和一个基于 Next.js 的参考实现(位于 examples/widget/ 目录)。这些实现支持浮动"启动器"模式和"内联"模式,在宿主站点和 Onyx 后端之间提供了无缝桥接。
系统概览与集成
该组件作为一个独立客户端运行,直接与 Onyx FastAPI 后端通信。它利用服务器发送事件(SSE)实现实时消息流式传输,并通过 API 密钥处理认证。
关键组件角色
- Lit Web 组件:将 UI、样式和状态管理封装到自定义 HTML 元素中,并使用 Shadow DOM 进行隔离。
- Next.js 参考实现:位于
examples/widget/目录中的基于 React 的示例,展示了 Onyx 聊天协议的手动实现examples/widget/src/app/widget/Widget.tsx:1-255。 - 启动器模式:显示一个浮动气泡(通常位于右下角),点击后打开聊天抽屉。
- 内联模式:将聊天界面直接嵌入到宿主页面的特定容器中。
- SSE 集成:管理与后端流式端点的连接,以提供响应式的打字体验
examples/widget/src/app/widget/Widget.tsx:57-85。
数据流架构
下图展示了宿主网站、组件客户端和 Onyx 后端服务之间的交互。
组件交互流程
来源:examples/widget/src/app/widget/Widget.tsx:87-152,examples/widget/src/app/widget/Widget.tsx:170-188
配置与属性
组件通过环境变量(在 Next.js 示例中)或 HTML 属性(在 Lit 组件中)进行配置。
| 参数 | 描述 | 来源 |
|---|---|---|
NEXT_PUBLIC_API_URL | Onyx 后端实例的基础 URL。 | examples/widget/src/app/widget/Widget.tsx:6 |
NEXT_PUBLIC_API_KEY | 用于 Bearer 认证的 API 密钥。 | examples/widget/src/app/widget/Widget.tsx:7 |
persona_id | 要使用的助手的特定 ID(默认为 0)。 | examples/widget/src/app/widget/Widget.tsx:108 |
primary-color | (仅 Lit)用于主题自定义的 CSS 颜色字符串。 | examples/widget/README.md:64-66 |
mode | (仅 Lit)launcher(浮动)或 inline。 | examples/widget/README.md:38-53 |
实现细节
消息编排
与 Onyx 交互的核心逻辑位于 sendMessage 函数中 examples/widget/src/app/widget/Widget.tsx:87-152。对于新对话,它遵循两步流程:
- 会话创建:使用
persona_id调用/chat/create-chat-sessionexamples/widget/src/app/widget/Widget.tsx:98-121。 - 消息分发:使用
chat_session_id、message文本和默认的retrieval_options(将run_search设置为 "always")调用/chat/send-messageexamples/widget/src/app/widget/Widget.tsx:123-144。
流式传输与片段处理
由于网络中间件(如 Nginx)可能会批处理或分片 SSE 片段,组件实现了一种健壮的解析策略:
processSingleChunk:尝试将字符串解析为 JSON。如果失败,则假定该片段不完整,并将其作为partialChunk返回examples/widget/src/app/widget/Widget.tsx:11-24。processRawChunkString:按换行符分割传入数据,并管理部分片段的缓冲区,以确保流读取之间不会丢失数据examples/widget/src/app/widget/Widget.tsx:26-55。handleStream:一个异步生成器,向 UI 层生成解析后的对象数组examples/widget/src/app/widget/Widget.tsx:57-85。
代码实体映射:流式逻辑
来源:examples/widget/src/app/widget/Widget.tsx:11-85
部署与构建
Next.js 示例 (示例/widget)
此版本是一个标准的 Next.js 应用程序,专为快速原型设计而构建。
- 设置:需要执行
npm iexamples/widget/README.md:16-17。 - 构建:使用
next build创建生产就绪的独立包examples/widget/package.json:7。 - 环境:通过
.env文件进行配置examples/widget/.env.example:1-2。
Lit Web 组件 (widget/)
基于 Lit 的组件专为广泛兼容性而设计。
- Shadow DOM:确保组件的样式(例如来自
react-markdown的样式)不会与宿主页面冲突examples/widget/package.json:15。 - 构建模式:
build:cloud:为 Onyx Cloud 端点配置。build:self-hosted:为自定义后端 URL 配置。
浏览器兼容性
该组件利用了现代 Web 标准:
- 自定义元素(V1):用于
<onyx-chat-widget>标签。 - Fetch API 与 ReadableStreams:用于处理消息流
examples/widget/src/app/widget/Widget.tsx:60-65。 - ES2017+:针对现代浏览器环境
examples/widget/tsconfig.json:29。
来源:examples/widget/package.json:1-29,examples/widget/README.md:1-71,examples/widget/src/app/widget/Widget.tsx:1-255,examples/widget/tsconfig.json:1-41