|
1 | 1 | # N0Mail (M2 Alpha) |
2 | 2 |
|
3 | | -AI Email Assistant based on `m2design.mdc`. |
| 3 | +AI Email Assistant |
4 | 4 |
|
5 | | -## 目标 (Goals - M2 Alpha) |
| 5 | +## Goals (M2 Alpha) |
6 | 6 |
|
7 | | -* **自动简报**: 每日 08:00 自动生成 Markdown 简报 (`brief.md`) 保存本地目录 `~/.n0mail/briefs/` |
8 | | -* **手动触发**: CLI `n0mail brief run [--date]` 随时生成,15 min 缓存确保幂等 |
9 | | -* **交互追问**: CLI `n0mail chat` REPL:RAG 检索本地邮件 → GPT-4o 流式回答 |
10 | | -* **离线存储**: 本地 SQLite + ChromaDB 保存最近 45 天邮件元数据、正文、标签、摘要、嵌入 |
| 7 | +* **Automatic Briefing**: Automatically generate a Markdown briefing (`brief.md`) daily at 08:00 and save it to the local directory `~/.n0mail/briefs/`. |
| 8 | +* **Manual Trigger**: Generate the briefing on demand using `n0mail brief run [--date]`, with a 15-minute cache to ensure idempotency. |
| 9 | +* **Interactive Chat**: Use the CLI `n0mail chat` REPL: Perform RAG search on local emails → Stream answers using GPT-4o. |
| 10 | +* **Offline Storage**: Store metadata, body, labels, summaries, and embeddings of the last 45 days of emails locally using SQLite + ChromaDB. |
11 | 11 |
|
12 | | -## 功能 (Features - M2 Alpha) |
| 12 | +## Features (M2 Alpha) |
13 | 13 |
|
14 | | -* ✅ **F-1: Gmail OAuth**: `n0mail auth google` 完成 PKCE 流程 → 保存 token 于 `keyring` |
15 | | -* ✅ **F-2: 邮件同步**: `n0mail sync run` 使用 `historyId` (默认) 或时间范围 (`--days`) 增量抓取,或全量 (`--full`) 获取最新邮件。写入 DB 并生成嵌入向量存入 ChromaDB。 |
16 | | -* ✅ **F-3: 零样本分类**: `n0mail process classify` GPT-4o function-call → `label` 字段写回 (默认处理所有未分类邮件) |
17 | | -* ✅ **F-4: 邮件摘要**: `n0mail process summarize` GPT-4o 摘要 → `summary` 字段写回 (Bulk/Promo 可选跳过) |
18 | | -* ✅ **F-5: 简报拼装**: `n0mail brief compose` 根据本地数据规则生成简报 / `n0mail brief generate` 使用 OpenAI 生成简报。 |
19 | | -* ⏳ **F-6: 自动生成**: Cron (`n0mail cron enable`) → 调 `brief run --today` |
20 | | -* ✅ **F-7: CLI 交互**: `n0mail chat`:RAG 检索 → GPT-4o Stream |
21 | | -* ⏳ **F-8: 命令补全**: `/open id`, `/copy`, `/retry` |
22 | | -* ⏳ **F-9: 缓存策略**: `brief_cache` 表 |
| 14 | +* ✅ **F-1: Gmail OAuth**: `n0mail auth google` completes the PKCE flow → saves the token in `keyring`. |
| 15 | +* ✅ **F-2: Email Sync**: `n0mail sync run` uses `historyId` (default) or a date range (`--days`) for incremental fetching, or `--full` for fetching the latest emails. Writes to the DB and generates embeddings stored in ChromaDB. |
| 16 | +* ✅ **F-3: Zero-Shot Classification**: `n0mail process classify` uses GPT-4o function-call → writes the `label` field back (processes all unclassified emails by default). |
| 17 | +* ✅ **F-4: Email Summarization**: `n0mail process summarize` uses GPT-4o for summarization → writes the `summary` field back (optionally skips Bulk/Promo). |
| 18 | +* ✅ **F-5: Briefing Composition**: `n0mail brief compose` generates a briefing based on local data rules / `n0mail brief generate` uses OpenAI to generate the briefing. |
| 19 | +* ⏳ **F-6: Automatic Generation**: Cron (`n0mail cron enable`) → calls `brief run --today`. |
| 20 | +* ✅ **F-7: CLI Interaction**: `n0mail chat`: RAG retrieval → GPT-4o Stream. |
| 21 | +* ⏳ **F-8: Command Completion**: `/open id`, `/copy`, `/retry`. |
| 22 | +* ⏳ **F-9: Caching Strategy**: `brief_cache` table. |
23 | 23 |
|
24 | | -## 使用方法 (Usage) |
| 24 | +## Usage |
25 | 25 |
|
26 | | -1. **安装依赖**: |
| 26 | +1. **Install Dependencies**: |
27 | 27 | ```bash |
28 | 28 | pip install poetry |
29 | 29 | poetry install # Includes markdownify, beautifulsoup4 |
30 | 30 | ``` |
31 | 31 |
|
32 | | -2. **配置**: |
33 | | - * 从 Google Cloud Console 下载 OAuth 客户端 ID (桌面应用类型) 的 `credentials.json` 文件,并将其重命名或保存为 `client_secret_....json` 放到项目根目录。 |
34 | | - * 创建 `.env` 文件在项目根目录,并添加你的 API 密钥 (根据你选择的 Provider): |
| 32 | +2. **Configuration**: |
| 33 | + * Download the OAuth client ID (`credentials.json` file for Desktop application type) from the Google Cloud Console and rename or save it as `client_secret_....json` in the project root directory. |
| 34 | + * Create a `.env` file in the project root directory and add your API key (depending on the provider you choose): |
35 | 35 | ```dotenv |
36 | | - # --- OpenAI (默认) --- |
| 36 | + # --- OpenAI (Default) --- |
37 | 37 | # OPENAI_API_KEY_N0MAIL="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" |
38 | | - |
| 38 | +
|
39 | 39 | # --- Ollama --- |
40 | 40 | # LLM_PROVIDER=ollama |
41 | 41 | # EMBEDDING_PROVIDER=ollama |
42 | | - # OLLAMA_HOST="http://localhost:11434" # Ollama 服务地址 |
43 | | - # # 指定 Ollama 模型 (示例) |
| 42 | + # OLLAMA_HOST="http://localhost:11434" # Ollama service address |
| 43 | + # # Specify Ollama models (example) |
44 | 44 | # CLASSIFY_DEFAULT_MODEL=llama3:8b |
45 | 45 | # SUMMARIZE_DEFAULT_MODEL=llama3:8b |
46 | | - # EMBEDDING_DEFAULT_MODEL=nomic-embed-text # 确保已 pull |
| 46 | + # EMBEDDING_DEFAULT_MODEL=nomic-embed-text # Ensure it's pulled |
47 | 47 | # BRIEF_DEFAULT_MODEL=llama3:instruct |
48 | 48 | # CHAT_DEFAULT_MODEL=llama3:instruct |
49 | | - |
50 | | - # --- 也可以混合使用 Provider --- |
| 49 | +
|
| 50 | + # --- Can also mix providers --- |
51 | 51 | # LLM_PROVIDER=openai |
52 | 52 | # EMBEDDING_PROVIDER=ollama |
53 | 53 | # OPENAI_API_KEY_N0MAIL="sk-xxxxxxxx" |
54 | 54 | # EMBEDDING_DEFAULT_MODEL=nomic-embed-text |
55 | 55 | # OLLAMA_HOST="http://localhost:11434" |
56 | 56 | ``` |
57 | | - * **(重要)** 确保 `client_secret_....json` 和 `.env*` 已添加到 `.gitignore` 文件中。 |
58 | | - * **(环境变量说明)**: |
59 | | - * `LLM_PROVIDER`: 设置用于聊天、分类、摘要、简报生成的提供商。支持: `openai` (默认), `ollama`。 |
60 | | - * `EMBEDDING_PROVIDER`: 设置用于生成嵌入向量的提供商。支持: `openai` (默认), `ollama`。如果未设置,默认跟随 `LLM_PROVIDER`。 |
61 | | - * `OPENAI_API_KEY_N0MAIL`: OpenAI API 密钥 (如果使用 `openai` 提供商)。 |
62 | | - * `OLLAMA_HOST`: Ollama 服务地址 (如果使用 `ollama` 提供商),默认 `http://localhost:11434`。 |
63 | | - * `CLASSIFY_DEFAULT_MODEL`: 分类默认模型 (默认: `gpt-4o-mini`)。 |
64 | | - * `SUMMARIZE_DEFAULT_MODEL`: 摘要默认模型 (默认: `gpt-4o-mini`)。 |
65 | | - * `EMBEDDING_DEFAULT_MODEL`: 嵌入默认模型 (OpenAI 默认: `text-embedding-3-small`, Ollama 需指定)。 |
66 | | - * `BRIEF_DEFAULT_MODEL`: 简报生成默认模型 (默认: `gpt-4o`)。 |
67 | | - * `CHAT_DEFAULT_MODEL`: 聊天默认模型 (默认: `gpt-4o`)。 |
68 | | - * (命令行中的 `--model` 或 `--embed-model` 选项会覆盖这些默认值)。 |
69 | | - |
70 | | -3. **运行命令** (使用 `poetry run n0mail <command>`): |
| 57 | + * **(Important)** Ensure `client_secret_....json` and `.env*` are added to your `.gitignore` file. |
| 58 | + * **(Environment Variable Explanation)**: |
| 59 | + * `LLM_PROVIDER`: Sets the provider for chat, classification, summarization, and briefing generation. Supported: `openai` (default), `ollama`. |
| 60 | + * `EMBEDDING_PROVIDER`: Sets the provider for generating embeddings. Supported: `openai` (default), `ollama`. Defaults to `LLM_PROVIDER` if not set. |
| 61 | + * `OPENAI_API_KEY_N0MAIL`: OpenAI API key (if using `openai` provider). |
| 62 | + * `OLLAMA_HOST`: Ollama service address (if using `ollama` provider), default `http://localhost:11434`. |
| 63 | + * `CLASSIFY_DEFAULT_MODEL`: Default model for classification (default: `gpt-4o-mini`). |
| 64 | + * `SUMMARIZE_DEFAULT_MODEL`: Default model for summarization (default: `gpt-4o-mini`). |
| 65 | + * `EMBEDDING_DEFAULT_MODEL`: Default model for embedding (OpenAI default: `text-embedding-3-small`, Ollama requires specification). |
| 66 | + * `BRIEF_DEFAULT_MODEL`: Default model for briefing generation (default: `gpt-4o`). |
| 67 | + * `CHAT_DEFAULT_MODEL`: Default model for chat (default: `gpt-4o`). |
| 68 | + * (Command-line options like `--model` or `--embed-model` override these defaults). |
| 69 | + |
| 70 | +3. **Run Commands** (using `poetry run n0mail <command>`): |
71 | 71 | ```bash |
72 | | - # --- 帮助 --- |
| 72 | + # --- Help --- |
73 | 73 | poetry run n0mail --help |
74 | 74 | poetry run n0mail auth --help |
75 | 75 | poetry run n0mail sync --help |
76 | 76 | poetry run n0mail process --help |
77 | 77 | poetry run n0mail brief --help |
78 | 78 |
|
79 | | - # --- 认证 --- |
80 | | - # 首次运行进行 Google 授权 |
| 79 | + # --- Authentication --- |
| 80 | + # Run for the first time for Google authorization |
81 | 81 | poetry run n0mail auth google |
82 | | - # 强制重新授权 |
| 82 | + # Force re-authorization |
83 | 83 | poetry run n0mail auth google --force |
84 | 84 |
|
85 | | - # --- 同步 --- |
86 | | - # 增量同步 (默认模式, 基于上次记录) |
| 85 | + # --- Sync --- |
| 86 | + # Incremental sync (default mode, based on last record) |
87 | 87 | poetry run n0mail sync run |
88 | | - # 同步过去7天的邮件 (最多3000封) |
| 88 | + # Sync emails from the past 7 days (max 3000) |
89 | 89 | poetry run n0mail sync run --days 7 |
90 | | - # 同步过去3天的邮件,最多只处理100封 |
| 90 | + # Sync emails from the past 3 days, process max 100 emails |
91 | 91 | poetry run n0mail sync run --days 3 --max-emails 100 |
92 | | - # 强制全量同步最新的3000封 (忽略天数和历史) |
| 92 | + # Force full sync of the latest 3000 emails (ignores days and history) |
93 | 93 | poetry run n0mail sync run --full |
94 | | - # 强制全量同步最新的50封 |
| 94 | + # Force full sync of the latest 50 emails |
95 | 95 | poetry run n0mail sync run --full --max-emails 50 |
96 | | - # 同步时不生成嵌入向量 |
| 96 | + # Sync without generating embeddings |
97 | 97 | poetry run n0mail sync run --no-embed |
98 | | - # 指定嵌入时使用的文本分割块大小和重叠 |
| 98 | + # Specify chunk size and overlap for embedding text splitting |
99 | 99 | poetry run n0mail sync run --chunk-size 8000 --chunk-overlap 100 |
100 | 100 |
|
101 | | - # --- 处理 (需要OpenAI Key) --- |
102 | | - # 分类所有未分类邮件 |
| 101 | + # --- Process (Requires OpenAI Key) --- |
| 102 | + # Classify all unclassified emails |
103 | 103 | poetry run n0mail process classify |
104 | | - # 限制数量、强制重新分类、指定模型 |
| 104 | + # Limit number, force reclassify, specify model |
105 | 105 | poetry run n0mail process classify --max-emails 10 --reclassify --model gpt-4o-mini |
106 | 106 |
|
107 | | - # 摘要所有未摘要邮件 (默认跳过 Bulk/Promo) |
| 107 | + # Summarize all unsummarized emails (skips Bulk/Promo by default) |
108 | 108 | poetry run n0mail process summarize |
109 | | - # 限制数量、强制重新摘要、指定模型 |
| 109 | + # Limit number, force resummarize, specify model |
110 | 110 | poetry run n0mail process summarize --max-emails 10 --resummarize --model gpt-4o-mini |
111 | | - # 摘要邮件, 不跳过 Bulk/Promo |
| 111 | + # Summarize emails, do not skip Bulk/Promo |
112 | 112 | poetry run n0mail process summarize --no-skip-bulk |
113 | 113 |
|
114 | | - # --- 简报 --- |
115 | | - # 生成过去1天的简报并打印 (基于规则) |
| 114 | + # --- Briefing --- |
| 115 | + # Generate briefing for the past 1 day and print (rule-based) |
116 | 116 | poetry run n0mail brief compose |
117 | | - # 生成过去3天的简报并保存到文件 |
| 117 | + # Generate briefing for the past 3 days and save to file |
118 | 118 | poetry run n0mail brief compose --days 3 --output ~/briefs/$(date +%Y-%m-%d)-brief.md |
119 | 119 |
|
120 | | - # 生成过去1天的简报并打印 (使用 OpenAI,需要 API Key) |
| 120 | + # Generate briefing for the past 1 day and print (using OpenAI, requires API Key) |
121 | 121 | poetry run n0mail brief generate |
122 | | - # 使用AI生成过去3天的简报, 包含 Bulk/Promo, 使用 gpt-4o-mini 模型, 保存到文件 |
| 122 | + # Use AI to generate briefing for past 3 days, include Bulk/Promo, use gpt-4o-mini model, save to file |
123 | 123 | poetry run n0mail brief generate --days 3 --include-bulk --model gpt-4o-mini --output ~/briefs/$(date +%Y-%m-%d)-ai-brief.md |
124 | | - # 使用AI生成简报,限制发送给 AI 的邮件数量为 15 |
| 124 | + # Use AI to generate briefing, limit emails sent to AI to 15 |
125 | 125 | poetry run n0mail brief generate --max-emails 15 |
126 | 126 |
|
127 | | - # --- 交互式聊天 (需要配置 Provider) --- |
128 | | - # 启动聊天会话 (使用配置的默认模型) |
| 127 | + # --- Interactive Chat (Requires Provider Config) --- |
| 128 | + # Start chat session (uses configured default model) |
129 | 129 | poetry run n0mail chat |
130 | | - # 指定聊天和嵌入模型, 并开启 Debug 输出 |
| 130 | + # Specify chat and embedding models, enable Debug output |
131 | 131 | poetry run n0mail chat --chat-model llama3:instruct --embedding-model nomic-embed-text --debug |
132 | | - # 指定初始简报的天数 |
| 132 | + # Specify number of days for initial briefing |
133 | 133 | poetry run n0mail chat --brief-days 7 |
134 | | - # (在聊天中输入 /quit 或 /exit 退出, /help 查看可用命令 - 如果实现) |
| 134 | + # (Enter /quit or /exit in chat to leave, /help to see available commands - if implemented) |
135 | 135 |
|
136 | | - # --- 其他 --- |
137 | | - # 查看版本 |
| 136 | + # --- Other --- |
| 137 | + # Check version |
138 | 138 | poetry run n0mail version |
139 | 139 | ``` |
140 | 140 |
|
141 | | -## 开发 |
| 141 | +## Development |
142 | 142 |
|
143 | | -* 运行测试: `poetry run pytest` |
144 | | -* 代码检查/格式化: `poetry run ruff check . --fix` 和 `poetry run ruff format .` |
| 143 | +* Run tests: `poetry run pytest` |
| 144 | +* Lint/Format code: `poetry run ruff check . --fix` and `poetry run ruff format .` |
0 commit comments