用 PyWebView + React 造了一个 ChromaDB 桌面客户端
背景
在用 ChromaDB 做本地向量数据库开发时,调试过程相当繁琐——要么写脚本查数据,要么对着 HTTP 接口手敲 curl。官方没有提供图形化管理界面,社区里的 Web 方案又需要额外起服务、开浏览器,体验割裂。
所以我用业余时间做了Chroma Walnut UI:一个基于 PyWebView + React 的原生桌面客户端,支持 Windows / macOS / Linux,无需安装 Python 环境即可直接运行。
GitHub:https://github.com/a605204746/Chroma-Walnut-UI
功能一览
- 多连接管理:同时管理多个 ChromaDB 连接(本地目录 / HTTP 服务),支持 Bearer Token 认证,一键测试连通性
- 集合管理:创建、重命名、编辑 Metadata、删除集合
- 文档浏览:分页展示(10 / 20 / 30 条可选),Metadata 彩色标签,支持查看完整 JSON 和框选复制
- 向量搜索:配置嵌入模型后输入文本即可进行语义相似度搜索,支持多条件过滤
- 向量模型配置:集合级别配置,兼容 OpenAI Embeddings 格式,内置 Ollama / OpenAI / LM Studio / 通义千问快速填充
- 一键生成测试数据:内置 50 条中文示例文档,配置好模型后一键插入
- 国际化 + 主题切换:中文 / English 随时切换,支持亮色 / 暗色 / 跟随系统
技术选型
| 层 | 选择 | 原因 |
|---|---|---|
| 桌面容器 | PyWebView 6 | 用系统原生 WebView 渲染,无需 Electron,包体极小 |
| 后端 | Python 3.12 + ChromaDB 0.6 | ChromaDB 官方 Python SDK,直接调用,无 HTTP 中转 |
| 前端框架 | React 19 + TypeScript | 生态成熟,类型安全 |
| UI 组件库 | Ant Design 6 | 开箱即用的企业级组件,内置暗色主题 |
| 状态管理 | Zustand 5 | 轻量,不需要 Redux 那么重 |
| 国际化 | i18next + react-i18next | 标准方案,切换零刷新 |
| 构建工具 | Vite 8 | 开发热更新快,构建产物小 |
| Python 包管理 | uv | 比 pip 快 10-100 倍,lockfile 可靠 |
| 打包 | PyInstaller | 三平台统一打包脚本 |
为什么选 PyWebView 而不是 Electron?
Electron 打包出来动辄 150MB+,本质上是把 Chromium 塞进去。PyWebView 直接调用操作系统已有的 WebView:
- Windows:Edge WebView2(Windows 10 1803+ 内置)
- macOS:WKWebView(系统内置)
- Linux:WebKitGTK
最终打包产物 Windows 约 40MB,用户无需安装 Python 或 Node.js,解压即用。
架构设计
┌─────────────────────────────────────┐ │ PyWebView 窗口 │ │ ┌──────────────────────────────┐ │ │ │ React 前端(TypeScript) │ │ │ │ Ant Design / Zustand │ │ │ └──────────┬───────────────────┘ │ │ │ window.pywebview.api │ │ ┌──────────▼───────────────────┐ │ │ │ Python API 层 (api.py) │ │ │ │ ChromaManager │ │ │ │ Embedding 配置管理 │ │ │ └──────────┬───────────────────┘ │ │ │ │ │ ┌──────────▼───────────────────┐ │ │ │ ChromaDB SDK │ │ │ └──────────────────────────────┘ │ └─────────────────────────────────────┘前后端通信走 PyWebView 的js_api机制:Python 类的公开方法自动暴露为window.pywebview.api.*,前端通过 TypeScript 封装的 bridge 调用,类型安全有保障。
// frontend/src/api/bridge.ts(精简示例)exportconstapi={listConnections:()=>window.pywebview.api.list_connections()asPromise<Connection[]>,queryDocuments:(connId:string,collection:string,params:QueryParams)=>window.pywebview.api.query_documents(connId,collection,params),}几个实现细节
单实例锁
用绑定本地端口的方式实现单实例,进程退出时端口自动释放,跨平台无需平台特定 API:
_INSTANCE_PORT=19527def_acquire_instance_lock()->bool:global_instance_socktry:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,0)s.bind(("127.0.0.1",_INSTANCE_PORT))s.listen(1)_instance_sock=sreturnTrueexceptOSError:returnFalse开发模式 vs 生产模式
# 开发模式:前端走 Vite 热更新uv run python main.py--dev# 生产模式:先 npm run build,再加载 dist/index.htmluv run python main.pymain.py启动时检测--dev参数,自动拉起 Vite dev server 并等待端口就绪后再创建窗口,开发体验与纯前端项目一致。
响应式布局
窗口宽度 < 1100px 时侧边栏自动折叠,字体和间距用 CSSclamp()自适应缩放,适配从 900px 到 1920px 的各种分辨率。
向量模型兼容设计
Chroma Walnut UI 不绑定任何特定的向量服务,只要接口兼容 OpenAI Embeddings 格式(POST /v1/embeddings)就可以接入:
| 服务 | 地址示例 |
|---|---|
| Ollama | http://localhost:11434/v1/embeddings |
| OpenAI | https://api.openai.com/v1/embeddings |
| LM Studio | http://localhost:1234/v1/embeddings |
| 通义千问 | https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings |
配置保存在~/.chroma_walnut_ui/collection_embeddings.json,每个集合独立配置,不写注册表,不污染系统目录。
CI/CD:三平台自动发布
.github/workflows/release.yml在推送版本 tag 时触发,三个平台并行构建:
gittag v1.0.0gitpush origin v1.0.0工作流分别在windows-latest、macos-latest、ubuntu-24.04上运行同一个build.py脚本,完成后将三个压缩包上传至 GitHub Release,无需手动在各系统上分别打包。
Linux 构建需要预装 WebKitGTK 头文件,这部分在 CI 里用apt-get解决:
-name:Install system dependenciesrun:|sudo apt-get install -y \ libgirepository-2.0-dev gcc \ libcairo2-dev pkg-config python3-dev \ gir1.2-gtk-3.0 gir1.2-webkit2-4.1 \ libwebkit2gtk-4.1-dev本地运行
gitclone https://github.com/[your-github-username]/chroma-walnut-ui.gitcdchroma-walnut-ui# 安装 Python 依赖(推荐 uv)uvsync# 安装前端依赖cdfrontend&&npminstall&&cd..# 启动(生产模式)uv run python main.py# 开发模式(前端热更新)cdfrontend&&npmrun dev&uv run python main.py--dev打包为可执行文件
uv run python build.py# 正式包uv run python build.py--debug# 调试包(保留控制台)脚本自动完成:检查依赖 → 构建前端 → 生成图标 → PyInstaller 打包 → 压缩分发文件。
| 平台 | 输出 |
|---|---|
| Windows | ChromaWalnutUI-Windows.zip |
| macOS | ChromaWalnutUI-macOS.dmg |
| Linux | ChromaWalnutUI-Linux.tar.gz |
小结
PyWebView + React 这个组合对于需要桌面原生窗口但又不想放弃 Web 前端生态的项目是个不错的选择。相比 Electron,它轻量很多;相比纯 Web 应用,它不需要用户开浏览器,体验更接近原生应用。
ChromaDB 生态里的工具目前还不多,欢迎 Star、提 Issue 或 PR,一起把这个工具做得更完善。
GitHub:https://github.com/a605204746/Chroma-Walnut-UI