☰
如何用 Tauri + Rust 打造 2.5k Star 开源笔记 NoteGen?TaoToken 开发心得
2026/10/2 17:03:18 网站建设 项目流程

1. 从碎片记录到知识库:NoteGen 要解决的真实问题

我平时写代码、开会、看文档,信息像沙子一样从指缝溜走。截图、代码片段、临时灵感散落在不同 App 里,想整理成一篇能读的文章,往往要手动复制粘贴半小时。NoteGen 这个项目就是冲着这个痛点去的:它是一款基于 Tauri 的 Markdown 笔记应用,GitHub 上已经拿到 2.5k Star,核心思路是用 AI 把「记录」和「写作」桥接起来,让碎片化内容自动变成可读草稿。

它适合谁?三类人最明显:一是开发者,需要随手存代码片段和报错日志;二是写作者,需要把零散素材整理成文章;三是效率工具爱好者,喜欢本地优先、数据自己掌控的笔记方案。NoteGen 的安装包只有 20MB 左右,支持 Mac、Windows、Linux,这背后就是 Tauri 的功劳——用 Rust 做内核保证性能和安全,前端仍然用你熟悉的 HTML/JS 写界面。

这篇文章不聊虚的,我会把 NoteGen 的工程化落地拆开:Tauri 配置怎么写、Rust 后端命令怎么组织、多端打包怎么验证,以及怎么通过 TaoToken 统一 Key 和 API 通道,把 AI 能力接进桌面端。你跟着做,能跑出一个可构建、可调试、可接入 AI 的本地版本。

先说清楚一个边界:NoteGen 是笔记应用,不是编辑器替代品,它的价值在于「记录 → 整理 → 写作」这条链路。Tauri 在这里的角色是容器和桥接层,Rust 负责文件系统、OCR、网络请求这些重活,前端负责交互。理解这个分工,后面配置才不会乱。

2. TaoToken 前置:统一 Key 与 API 通道的接入准备

在给 NoteGen 接 AI 能力之前,先解决一个工程问题:模型调用如果散落在前端各处,Key 会暴露、切换模型要改代码、不同厂商的接口格式还不一样。我的做法是走 TaoToken 统一通道,把 Base URL、Key、Model ID 三件套集中管理,前端只调一个本地 Rust 命令,Rust 再去请求统一 API。

TaoToken 的定位是 AI 能力接入层,官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。你需要先拿到一个 API Key,然后把它写进本地配置,而不是硬编码在前端代码里。这一步很关键,因为 Tauri 的前端产物是可以被解包的,Key 放前端等于公开。

具体操作路径:打开控制台创建 Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ;创建完在 API Keys 页面复制,地址是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。如果你只是想先验证模型通不通,可以用模型对话页面快速试一条请求,地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。

接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面写了请求格式和参数说明。如果你后面要做长期编码或 Agent 类功能,可以看 Coding Plan,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。Claude Code 相关的接入说明在 https://taotoken.net/claudecode?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 。

这里有个工程细节:NoteGen 的 AI 调用我放在 Rust 侧,用reqwest发请求,前端通过invoke调用。这样 Key 存在本地配置文件或环境变量里,前端拿不到明文。配置结构我习惯用 JSON,路径放在用户目录下的.notegen/config.json,和 NoteGen 的原文路径保持一致,方便你对照。

注意:不要把 Key 提交到 Git 仓库。建议在.gitignore里加上config.json和.env,本地开发用环境变量覆盖。

3. 可复制配置:Tauri + Rust 后端命令与 settings 片段

这一节给你能直接抄的配置。先看 Tauri 的核心配置文件src-tauri/tauri.conf.json,重点是窗口、构建命令和打包目标:

{ "build": { "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", "devPath": "http://localhost:1420", "distDir": "../dist" }, "package": { "productName": "NoteGen", "version": "0.1.0" }, "tauri": { "allowlist": { "fs": { "all": true, "scope": ["$APPDATA/*", "$DOCUMENT/*"] }, "shell": { "open": true }, "http": { "all": true, "scope": ["https://taotoken.net/*"] } }, "windows": [ { "title": "NoteGen", "width": 1200, "height": 800, "resizable": true } ], "bundle": { "active": true, "targets": ["dmg", "msi", "deb", "appimage"], "identifier": "com.notegen.app" } } }

allowlist.http.scope里我只放https://taotoken.net/*,这是最小权限原则,避免前端能请求任意域名。fs.scope限定在 APPDATA 和 DOCUMENT,笔记文件不会乱写。

再看 Rust 侧的 AI 调用命令,文件src-tauri/src/ai.rs:

use serde::{Deserialize, Serialize}; use reqwest::Client; #[derive(Serialize)] struct ChatRequest { model: String, messages: Vec<Message>, } #[derive(Serialize, Deserialize)] struct Message { role: String, content: String, } #[derive(Deserialize)] struct ChatResponse { choices: Vec<Choice>, } #[derive(Deserialize)] struct Choice { message: Message, } #[tauri::command] pub async fn chat_completion(prompt: String, model: String) -> Result<String, String> { let api_key = std::env::var("TAOTOKEN_API_KEY") .map_err(|_| "missing TAOTOKEN_API_KEY".to_string())?; let client = Client::new(); let body = ChatRequest { model, messages: vec![Message { role: "user".into(), content: prompt, }], }; let resp = client .post("https://taotoken.net/api/v1/chat/completions") .bearer_auth(api_key) .json(&body) .send() .await .map_err(|e| e.to_string())?; let data: ChatResponse = resp.json().await.map_err(|e| e.to_string())?; data.choices .into_iter() .next() .map(|c| c.message.content) .ok_or_else(|| "empty choices".to_string()) }

然后在src-tauri/src/main.rs里注册命令:

fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![ai::chat_completion]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }

前端调用就一行:

import { invoke } from "@tauri-apps/api/tauri"; const result = await invoke("chat_completion", { prompt: "把这段记录整理成周报", model: "gpt-4o-mini", });

三件套在这里体现得很清楚:Base URL 是https://taotoken.net/api,Key 走环境变量TAOTOKEN_API_KEY,Model ID 由前端传入。如果你用 Cline MCP 或 Codex 的auth.json做本地辅助开发,也按同样三件套填:Base URL、Key、Model ID,不要只填一半。

4. 验证请求与本地构建:从 dev 到多端打包

配置写完,先验证 AI 通道通不通。最直接的方式是在 Rust 侧写个测试,或者用 curl 打一条请求:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "用一句话解释 Tauri"}] }'

返回里能看到choices[0].message.content就说明通道正常。如果返回 401,先检查 Key 有没有复制完整;如果返回local proxy failed,检查你的网络请求是不是被本地代理拦了,Tauri 的allowlist.http.scope是否放行了taotoken.net。

通道通了之后跑本地开发:

pnpm install pnpm tauri dev

第一次编译 Rust 依赖会比较慢,耐心等。窗口起来后,在笔记里选中一段文字,触发 AI 整理,看能不能返回结果。这一步成功,说明前端 → Rust → TaoToken → 模型这条链路完整。

接着验证构建。多端打包命令:

pnpm tauri build

产物在src-tauri/target/release/bundle/下,Mac 出 dmg,Windows 出 msi,Linux 出 deb 和 AppImage。我实测下来,首次构建大概几分钟,增量构建快很多。如果你只想验证某一个平台,可以加--target参数,比如pnpm tauri build --target x86_64-pc-windows-msvc。

构建过程中常见的坑是图标缺失,Tauri 要求src-tauri/icons下有对应尺寸的 png 和 ico。用pnpm tauri icon path/to/logo.png自动生成一套,省得手动裁。

验证构建成功的标志:安装包能双击打开,笔记能新建、保存、重启后还在,AI 整理按钮能返回内容。这三条过了,工程化落地就算跑通了。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

接入过程里我踩过的坑集中在几个报错,逐个说清楚。

401 Unauthorized:最常见。原因通常是 Key 没读到、Key 失效、或者请求头格式不对。检查TAOTOKEN_API_KEY是否在当前 shell 生效,echo $TAOTOKEN_API_KEY看一下。Rust 里用std::env::var读环境变量,如果你在 IDE 里跑,记得在运行配置里也加上。请求头必须是Authorization: Bearer <key>,少个空格都会 401。

local proxy failed:这个报错一般出现在请求被本地网络层拦截时。先确认tauri.conf.json的allowlist.http.scope包含https://taotoken.net/*,再确认系统没有设置会干扰请求的本地转发规则。如果你在公司网络下,问一下网管是否放行了目标域名。这个错和 Key 无关,别去反复换 Key。

reading choices 报错:通常是响应结构和你反序列化的结构对不上。比如返回体里choices为空,或者字段名拼错。我建议先把原始响应println!出来看结构,再写Deserialize。另外注意有些模型返回的是流式,如果你没处理 SSE,直接resp.json()会失败。非流式请求记得在 body 里不要带stream: true。

OAuth 相关报错:如果你用 Claude Code 或 Codex 这类工具做辅助开发,遇到 OAuth 报错,多半是认证方式选错了。走 API Key 通道时不需要 OAuth 流程,直接填 Base URL、Key、Model ID 三件套即可。如果你在 CC Switch 或 Cline MCP 里配置,确认填的是 API Key 模式,而不是账号登录模式。三件套缺一个都会报认证失败。

排查顺序建议:先 curl 验证通道,再验证 Rust 命令,最后验证前端调用。一层层缩小范围,比一上来就改代码高效得多。

6. 语义一致 CTA:把 AI 能力稳定接进你的桌面端

NoteGen 这类 Tauri 应用的工程化,核心就三件事:配置最小权限、Rust 侧收口敏感逻辑、AI 通道统一管理。你把 Base URL、Key、Model ID 三件套固定下来,后面换模型、加功能都不用动前端。

如果你要复现这套接入,建议按这个顺序走:先去 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 拿 Key,再对照 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 的请求格式写 Rust 命令,验证阶段用 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 快速试模型。长期做编码或 Agent 功能,可以看 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。

最后留一个实用技巧:把 AI 调用的超时和重试写在 Rust 侧,前端只负责展示 loading 和结果。桌面端网络环境比浏览器复杂,Rust 侧控制更稳。我试过在弱网下加 3 次重试,体验比前端重试好很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询