MarkAI:做一个属于自己的 AI 工作台

最近一直在整理 MarkAI。
它并不是一个只接入某一家模型的聊天页面,而是我想做成的一套 AI 工作台:可以在同一个界面里切换不同的模型,进行联网搜索,读取文件,生成文档、表格和图表,也可以把它部署在自己的服务器上。
项目地址:
https://github.com/markcxx/mark-ai
为什么要做一个自己的工作台
现在使用 AI 的场景越来越多,但不同的事情经常需要打开不同的工具。
普通对话在一个页面里,联网搜索在另一个页面里;需要分析 PDF 或表格时,要重新上传文件;想把回答整理成 Word 或 Excel,又要再做一次转换。
这些事情本身都不难,只是来回切换的次数多了以后,信息会被分散在不同的地方。
所以我想做一个相对集中的工作界面。模型只是其中的一部分,文件、工具、生成结果和会话本身也应该被当作同一条工作流来处理。
这个想法后来逐渐变成了 MarkAI。
一个以会话为中心的界面
MarkAI 的基本单位是会话。
左侧是会话列表,主区域负责消息和输入。用户可以在当前会话里选择模型、打开联网搜索、上传附件,或者启用某个工具。不同的能力不会被拆成互相孤立的页面,而是尽量留在同一条对话里。

桌面端的会话侧栏可以调整宽度,主面板则专注于消息、模型选择、附件和输入区。移动端会把侧栏切换成临时抽屉,同时保留消息操作和输入区域的安全边距。
我比较在意的是内容的阅读感。
普通模式会限制消息的阅读宽度,避免长文本铺满整个屏幕;需要查看表格、代码或图表时,又可以切换到宽屏模式。它们都是一些不显眼的选择,但会影响长时间使用时的感觉。
不同模型放在同一个入口
MarkAI 支持多种模型提供商。
Gemini 使用原生 runtime,其他大多数提供商则通过 OpenAI-compatible runtime 接入。模型在系统中使用 provider/model 的形式标识,因此即使不同供应商有同名模型,也不会混在一起。
目前仓库里提供了 Google Gemini、OpenAI、DeepSeek、MiniMax、Moonshot、阿里云百炼、智谱、OpenRouter、硅基流动、火山方舟、Groq、Mistral、Together AI、xAI、HuggingFace 和无问芯穹等提供商模板。
这些模板只负责提供默认的 Base URL、runtime 和一些推荐模型。真正使用时,仍然需要配置自己的 API Key 和模型列表。
这样做的好处是,模型切换不再需要修改页面代码。管理员或用户可以在设置中选择默认模型,也可以针对不同任务选择不同的模型。

消息不只有正文
在普通的聊天应用里,一条消息通常就是一段文本。但模型开始推理、调用工具、生成文件之后,单纯的文本结构就不够了。
MarkAI 会把正文、推理过程、工具调用、生成文件和翻译保存为不同类型的消息片段。
OpenAI-compatible 服务有时会返回结构化 reasoning,有时会在正文里使用 <think> 标签。服务端需要在任意 SSE 分块边界上把这些内容归一化,否则一个标签刚好被分成两半时,就可能把推理文本错误地显示到最终回答里。
现在消息可以显示推理过程、推理耗时、生成耗时和 token 用量,也支持停止、继续和重新生成。重新生成之后,不同版本的回复也会保留下来。

消息操作也尽量做得完整一些:复制、编辑、删除、翻译、语音朗读、选择到此处和批量操作都可以在消息上完成。
语音播放不是把整篇文本一次性塞进去,而是按消息片段处理。这样暂停、继续和重新播放时,都更容易对应到当前正在阅读的内容。
工具跟着会话走
MarkAI 里有一个插件中心,用来管理内置 Tool 和 Skill。
工具需要先安装到当前账户,再按会话启用。这样不同会话可以保持不同的工作方式:查资料的会话开启联网搜索,整理表格的会话开启计算或文件工具,普通聊天则不必加载额外能力。

目前内置工具包括联网搜索、网页阅读、可靠计算、Word 生成、Excel 生成、ECharts、Mermaid 和 Markmap 等。
模型可以先搜索网页,再根据引用继续回答;也可以读取上传的 PDF、DOCX、XLSX、CSV 或普通文本文件,然后把结果整理成新的内容。
工具的结果不会被当作普通文本直接拼到消息里,而是作为结构化片段保存。这样在重新打开会话时,原来的工具调用、来源和生成文件仍然能够被识别。
文件理解和生成
文件能力是我在 MarkAI 里比较重视的一部分。
上传文件之后,系统会按照类型进行处理:PDF、DOCX、XLSX、CSV 和常见文本可以提取内容,图片则作为附件交给模型理解。文件可以保存在本地目录,也可以在云端模式下使用 Cloudflare R2。

输入文件只是第一步。更有用的情况是,模型把分析结果继续生成可下载的文件。
例如让模型根据一份数据生成 Excel,或者把一段材料整理成 Word 文档;需要展示趋势时,可以生成 ECharts;需要表达层级关系时,可以生成 Mermaid 或 Markmap。
这些内容最后都会进入统一的文件存储和下载流程,而不是只能停留在聊天气泡里。
本地模式和云端模式
MarkAI 可以在本地运行,也可以部署成带账户系统的服务。
本地模式使用 SQLite,不需要配置账户系统。会话、设置、工具状态和用户文件都保存在当前服务器上,适合个人在电脑上使用。
云端模式则使用 PostgreSQL、Better Auth 和 Cloudflare R2。它提供邮箱登录、Google/GitHub SSO、注册策略、等候名单、用户管理和审计记录,更适合放到服务器上供多个用户使用。
两种模式共享同一套主要界面和业务逻辑,区别主要集中在数据存储、认证和文件服务上。
这也是我选择自托管的原因之一:想要简单使用时,可以只保留 SQLite;需要更完整的服务形态时,再切换到云端数据库和对象存储。
部署并不复杂
本地运行只需要 Node.js 22 和一个可用的模型 API Key:
git clone https://github.com/markcxx/mark-ai.gitcd mark-ainpm installcp .env.example .env.localnpm run dev然后打开 http://localhost:3000 即可。
仓库也提供了 Dockerfile 和 Compose 示例。生产环境可以使用 Next.js standalone 输出,把服务放在 Nginx、Caddy 或其他反向代理之后。
如果只想在本地使用,SQLite 模式已经足够;如果需要账户、多人使用和云端文件,则可以配置 PostgreSQL 和 Cloudflare R2。
还在继续整理
MarkAI 目前已经有了比较完整的工作台形状,但仍然有不少地方需要继续打磨。
模型供应商的接口会变化,文件解析也会遇到新的格式;复杂的生成任务需要更好的进度反馈,移动端还有一些交互可以继续简化。
我希望它最后保持一种安静的状态:不需要用户记住太多入口,也不需要为了完成一个小任务打开很多页面。模型、文件和工具各自完成自己的工作,然后在同一个会话里留下可以继续使用的结果。
MarkAI 的源码和部署说明都已经放在 GitHub:
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
