先说明一个我观察到的现象:很多人的笔记软件里躺着几千条从未回看过第二次的摘抄,收藏夹里囤着上百篇“以后有空再读”的文章。不是不想学,而是捕获、整理、内化、输出这条链路断裂了。信息进来之后没有下一步动作,自然谈不上产出。
Obsidian 常被用来解决“记没记住、能不能找回来”的问题,但只靠手动打标签、维护双向链接,时间一到还是会变成“整理笔记的时间比学新东西还多”。AI 的出现补上了这块短板:它可以帮你做初步归纳、生成可检索的摘要、把零散笔记批量转成结构化卡片,甚至可以直接把笔记草稿扩写成一篇完整文章。
本文将围绕“AI + Obsidian 智能学习产出工作流”展开一套可落地的实操方案。适合这几类读者:
- 正在用 Obsidian 做知识管理,但笔记越记越乱、产出效率偏低的学习者。
- 想用 AI 自动化处理笔记,但不清楚插件、脚本、本地模型之间的配合方式。
- 有一门技术、一个专业领域需要持续输入并转化为文章、文档或汇报材料的开发者。
全文不会只停留在概念层面。我会先解释 Obsidian 和 AI 在笔记场景中的角色定位,再给出环境准备、插件配置、核心代码、实际效果和排错清单。整个流程跑通之后,你可以实现这样的效果:一键把文章链接存进 Obsidian,自动生成摘要和标签;对一批笔记批量提问,获得带原文出处的回答;每天在 Daily Note 里写两句记录,AI 自动整理成周报。
1. 背景与核心概念:为什么是 Obsidian + AI?
1.1 Obsidian 的定位和它的长板
Obsidian 是一个基于 Markdown 文件的本地知识管理工具。它不像 Notion 那样需要联网才能访问,也不依赖某个云数据库格式。所有笔记都以.md文件存放在本地文件夹里,换个设备用同步盘一放,基本就能完整迁移。
它最核心的两个设计是:
- 双向链接:在 A 笔记中写
[[B]],Obsidian 会自动建立 A 到 B 的关联,同时 B 的反向链接面板会出现来自 A 的引用。 - Graph View(关系图谱):把笔记之间的链接关系可视化成一幅节点图,帮助使用者看到知识之间的潜在联系。
真正让 Obsidian 和普通 Markdown 编辑器拉开差距的,是插件生态。Templater 可以按模板生成日记和项目记录,Dataview 可以像数据库一样查询笔记元数据,QuickAdd 可以自定义捕获流程,Excalidraw 可以在笔记中直接画图。后面搭建工作流时会频繁用到这些插件。
1.2 AI 在知识工作流里的角色
先泼一盆冷水:AI 在这套工作流里并不是“帮你思考”的角色,而是“帮你处理信息”的角色。它擅长做归纳、改写、提取关键词、生成解释、批量把无结构文本转成结构化笔记;它不擅长代替你做判断、做决策、维护真实可信的知识体系。
具体到学习场景,AI 的工作可以拆成几条:
- 降低捕获成本:把网页内容、PDF 或笔记草稿丢给 AI,自动生成摘要、标签和关联词。
- 降低整理成本:同一主题的多篇笔记可以通过 AI 提取共同点,生成主题综述。
- 降低内化成本:对概念性内容,用 AI 解释、类比、生成练习题,变相做费曼学习法。
- 降低输出成本:把整理好的卡片、大纲交给 AI 扩写成文章初稿,再由人工修改。
1.3 工作流全景图
整套工作流可以划分为五个环节:
信息捕获 → AI 预处理 → 卡片整理 → 周期性聚合复盘 → 内容输出对应到 Obsidian 里的实际操作是:
- 捕获:通过浏览器剪藏、微信剪藏、手动粘贴,把素材存进
00 Inbox文件夹。 - 预处理:本地 Python 脚本或 Obsidian 插件调用 AI,为新增素材生成摘要、标签、关键词。
- 整理:把处理过的笔记移动到
10 Literature或20 Projects目录,并建立双链。 - 聚合复盘:用 Dataview 汇总近一周新增笔记;AI 根据 Daily Note 生成周回顾。
- 输出:选中某个主题的笔记,AI 辅助生成大纲和初稿,再导出 Word/PDF。
2. 环境准备与版本说明
2.1 系统环境和工具清单
本文示例以 Windows 为主,macOS/Linux 命令略有差异,但整体思路一致。
- 操作系统:Windows 10/11(macOS 13 以上同理)
- Obsidian:1.5 以上版本
- Python:3.10 或 3.11
- 模型方案:本地模型(Ollama)或在线 API 二选一
- 关键插件:Dataview、Templater、QuickAdd
- 辅助命令行工具:Git Bash(可选)
如果输入材料没有特定版本要求,一般以“当前 Obsidian 商店能搜到的最新稳定版”为准。注意:Obsidian 插件更新频率较高,不同大版本之间 API 有变化,部分旧插件可能失效。
2.2 Obsidian 下载与安装
很多新手卡在 Obsidian 下载这一步。网络环境不好时,官网下载可能很慢。这里建议:
- 优先从 Obsidian 官网下载安装包。
- 如果下载缓慢,可尝试更换网络环境,或使用国内开源镜像站提供的安装包。
- 安装过程非常简单,一直 Next 即可。
安装完成后,创建一个新的 Vault(仓库),建议命名为knowledge-base。之后所有笔记都放在这个目录下。
knowledge-base/ ├── 00 Inbox/ ├── 10 Literature/ ├── 20 Projects/ ├── 30 Permanent/ ├── 90 Templates/ └── Daily Notes/这个目录结构基本对应 Zettelkasten 卡片盒笔记法的简化版:Inbox 存放不成熟的想法和素材,Literature 存放原始来源与摘录,Permanent 存放经过消化的永久笔记,Templates 放模板,Daily Notes 放日记和日志。
2.3 Python 环境准备
工作流中的自动化脚本依赖 Python。如果你已经有 Anaconda 或 Miniconda,直接创建虚拟环境即可:
conda create -n obsidian-ai python=3.11 -y conda activate obsidian-ai如果没有 conda,也可以只用 venv:
python -m venv obsidian-ai-env # Windows obsidian-ai-env\Scripts\activate # macOS/Linux source obsidian-ai-env/bin/activate后面所有 Python 脚本都在这个虚拟环境中执行。核心依赖只有一个requests,用来发送 HTTP 请求调用模型服务。如果需要读取 Markdown 文件并修改 frontmatter,可以直接用 Python 标准库手动解析,不额外引入重量级依赖。
安装依赖:
pip install requests pyyaml说明:requests负责请求 API,pyyaml负责解析 Markdown 文件头部的 YAML 元数据。如果只是做最简单的 API 调用,requests就够用了。
3. 核心原理拆解:AI 如何与 Obsidian 笔记交互
在写代码之前,先理解整个方案的技术链路。Obsidian 本身不提供 AI 能力,AI 也无法直接读取 Obsidian 的内部数据库。两者结合有三种主流方式:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Obsidian 第三方 AI 插件(如 Copilot、Smart Connections) | 界面集成度高,操作简单 | 部分插件对网络和服务商有依赖,API 费用需自行配置 | 个人快速使用 |
| 本地 Python 脚本 + 模型 API | 灵活、可控、可批量处理 | 需要写一点脚本,不适合完全不会代码的用户 | 批量整理历史笔记 |
| 自建服务(FastAPI + 模型) | 可嵌入团队工作流,权限可控 | 部署成本高,维护复杂 | 团队知识库自动化 |
本文采用“本地 Python 脚本 + 模型 API”的方式做批量处理和自动化,因为它最透明、最容易排错,也最容易迁移到团队环境。
3.1 模型 API 选择:本地模型还是在线 API?
先看本地模型方案。使用 Ollama 运行开源模型(比如 Qwen、Llama 系列),数据不出本机,适合隐私要求高的场景,但需要一定的 CPU/GPU 资源。启动一个服务后,通过http://localhost:11434/api/generate发送请求。
再看在在线 API 方案。国内用户可以选择国内主流大模型服务商。这类接口普遍兼容 OpenAI 格式,配置一个base_url和api_key即可。优点是模型能力更强、响应更快,缺点是会有少量费用且内容需要传输到云端。
我的建议是:
- 如果只是给笔记做摘要和打标签,本地 7B 模型完全够用。
- 如果需要对长文做深度分析和改写,在线 API 体验更好。
- 对隐私敏感的学习笔记,一律走本地模型。
3.2 统一 API 调用设计
为了让脚本可以同时支持本地 Ollama 和在线 API,我们设计一个统一调用函数。
# -*- coding: utf-8 -*- """ 文件路径:scripts/ai_client.py 统一模型调用客户端,支持 Ollama 和 OpenAI 兼容接口 """ import os import json import requests from typing import Optional class AIClient: def __init__(self, provider: str = "ollama", **kwargs): """ provider: 'ollama' 或 'openai' """ self.provider = provider if provider == "ollama": self.base_url = kwargs.get("base_url", "http://localhost:11434") self.model = kwargs.get("model", "qwen2.5:7b") elif provider == "openai": self.base_url = kwargs.get("base_url", "https://api.openai.com/v1") self.api_key = kwargs.get("api_key", os.environ.get("AI_API_KEY", "")) self.model = kwargs.get("model", "gpt-4o-mini") else: raise ValueError(f"Unsupported provider: {provider}") def chat(self, messages: list, temperature: float = 0.3) -> str: """ 发送对话请求,返回文本结果 """ if self.provider == "ollama": url = f"{self.base_url}/api/chat" payload = { "model": self.model, "messages": messages, "stream": False, "options": { "temperature": temperature } } resp = requests.post(url, json=payload, timeout=120) resp.raise_for_status() data = resp.json() return data["message"]["content"].strip() elif self.provider == "openai": url = f"{self.base_url}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } payload = { "model": self.model, "messages": messages, "temperature": temperature } resp = requests.post(url, json=payload, headers=headers, timeout=120) resp.raise_for_status() data = resp.json() return data["choices"][0]["message"]["content"].strip()这个客户端的核心设计思想是:上层业务逻辑只调用chat()方法,不关心底层是本地模型还是在线 API。切换模型时,只需要把provider和base_url改一下即可。
3.3 Markdown 文件操作:frontmatter 读写
Obsidian 笔记的元数据存储在文件头部的 YAML frontmatter 中。格式长这样:
--- title: 注意力机制详解 tags: [深度学习, NLP] source: https://example.com status: processed summary: 本文介绍注意力机制的基本原理... --- 正文内容...自动化脚本需要读取和修改这个区域。用pyyaml来解析 YAML,但注意:YAML 中可能出现非标准内容,所以脚本要能容错。下面是一个读取 frontmatter 并写入摘要字段的函数:
# -*- coding: utf-8 -*- """ 文件路径:scripts/note_utils.py Markdown 文件 frontmatter 读取、更新工具 """ import re import yaml from pathlib import Path def read_note(file_path: str) -> dict: """ 读取 Markdown 笔记,返回 frontmatter 和正文 """ file_path = Path(file_path) text = file_path.read_text(encoding="utf-8") parts = text.split("---", 2) frontmatter = {} content = text if len(parts) >= 3: # 说明有 frontmatter try: frontmatter = yaml.safe_load(parts[1]) or {} except yaml.YAMLError: frontmatter = {} content = parts[2].strip() return { "frontmatter": frontmatter, "content": content, "raw": text } def update_frontmatter(file_path: str, updates: dict): """ 更新 Markdown 笔记的 frontmatter 字段 保留已有字段,只覆盖 updates 中的键 """ file_path = Path(file_path) note_info = read_note(str(file_path)) meta = note_info["frontmatter"] or {} meta.update(updates) # 生成新的 frontmatter new_meta_yaml = yaml.dump( meta, allow_unicode=True, sort_keys=False, default_flow_style=False ) # 构建新文件内容 new_content = f"---\n{new_meta_yaml}---\n\n{note_info['content']}\n" file_path.write_text(new_content, encoding="utf-8")这段代码的价值在于:不需要打开 Obsidian,就能批量对笔记做元数据更新。比如给所有没有摘要的笔记自动生成摘要、给所有 Inbox 中的笔记打上默认标签。
3.4 工作流中的依赖关系
从信息捕获到最终产出,完整链路如下:
- 捕获:Anthropic 风格的 Web Clipper、浏览器插件、手动复制进 Inbox。
- 预处理:Python 脚本扫描 Inbox 中的新文件,调用 AI 生成摘要和标签,写入 frontmatter。
- 整理:脚本根据标签自动移动文件,或在 Obsidian 中手动拖拽。
- 聚合:Dataview 查询每天新增的笔记,AI 根据 Daily Note 汇总成周报。
- 输出:用 Templater 创建文章草稿,引用相关笔记,AI 辅助扩写。
这套流程中,AI 不是独立运行的工具,而是嵌入到文件系统级别的自动化流水线里。理解这一点,后面看脚本逻辑就不会觉得乱。
4. 完整实战案例:搭建智能学习产出工作流
接下来是本文的核心部分。我会按步骤搭建一个最小可运行的闭环。整个过程不需要复杂的服务器,不需要信用卡,不依赖某个特定平台,你在自己电脑上就可以完整跑通。
4.1 创建项目目录与 Obsidian 目录结构
可以先在电脑上建一个总目录,比如D:\obsidian-ai-workflow,里面包含 Obsidian Vault 和项目脚本:
D:\obsidian-ai-workflow\ ├── knowledge-base\ # Obsidian Vault 根目录 │ ├── 00 Inbox\ │ ├── 10 Literature\ │ ├── 20 Projects\ │ ├── 30 Permanent\ │ ├── 90 Templates\ │ └── Daily Notes\ └── scripts\ ├── ai_client.py ├── note_utils.py └── process_inbox.py在 Obsidian 中打开knowledge-base这个文件夹即可。
4.2 安装核心插件
进入 Obsidian 后,按Ctrl+P打开命令面板,选择“设置” → “第三方插件” → “关闭安全模式”(如果默认开启),然后点击“浏览”,安装以下插件:
- Dataview:用于按元数据查询笔记,把笔记变成可过滤的数据库。
- Templater:用于根据模板快速创建笔记。
- QuickAdd:把常用动作绑定到快捷命令,比如“一键捕获到 Inbox”。
- Calendar:用于在侧边栏显示日期,快速创建 Daily Note。
安装之后,在插件设置中确认它们都切换到启用状态。
各插件在后续工作流中的具体用法:
- Dataview 负责“找笔记”。
- Templater 负责“建笔记”。
- QuickAdd 负责“收笔记”。
- Calendar 负责“记日记”。
4.3 配置 Templater 模板
在90 Templates目录下创建名为daily-note.md的模板文件,内容如下:
--- type: daily date: <% tp.date.now("YYYY-MM-DD") %> tags: [daily] --- # <% tp.date.now("YYYY-MM-DD dddd") %> ## 今日重点 - ## 阅读与输入 - ## 想法与输出 - ## 明日计划 -然后进入 Templater 设置,将“Template folder location”设为90 Templates,启用“Trigger Templater on new file creation”选项。这样每次新建笔记时,只要模板是新生成的 Daily Note,就会自动填充日期。
这个模板的每个板块都有明确作用:
今日重点:写下当天最重要的一件事。阅读与输入:记录看了什么文章、书、课程。想法与输出:记录灵感、写作方向、可产出的内容。明日计划:给第二天留一个轻量级 TODO。
4.4 编写 AI 预处理脚本
核心逻辑放在process_inbox.py中。这个脚本会扫描00 Inbox目录下的所有 Markdown 文件,对尚未生成摘要的笔记调用 AI 生成摘要、标签和关键词,并写入 frontmatter。
# -*- coding: utf-8 -*- """ 文件路径:scripts/process_inbox.py 功能:扫描 Inbox 文件夹,对没有摘要的笔记调用 AI 生成摘要、标签,更新 frontmatter 用法:python process_inbox.py --inbox ../knowledge-base/00\ Inbox --provider ollama """ import os import argparse from pathlib import Path from ai_client import AIClient from note_utils import read_note, update_frontmatter SYSTEM_PROMPT = """你是一名知识管理助手。请从用户的笔记文本中提取信息,并只输出 JSON。 JSON 格式如下: { "summary": "一句话摘要,不超过50字", "tags": ["标签1", "标签2"], "keywords": ["关键词1", "关键词2", "关键词3"] } 注意:不要输出 JSON 以外的任何文字。""" def process_file(file_path: Path, client: AIClient): note_info = read_note(str(file_path)) meta = note_info["frontmatter"] or {} # 已经处理过则跳过 if meta.get("status") == "processed": print(f"[SKIP] {file_path.name}") return content = note_info["content"] if len(content.strip()) < 10: print(f"[SKIP] {file_path.name} is empty") return messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"笔记内容:\n{content[:2000]}"} ] print(f"[INFO] Processing {file_path.name} ...") try: result = client.chat(messages, temperature=0.1) # 清理可能的 markdown 代码块包裹 result = result.replace("```json", "").replace("```", "").strip() ai_data = json.loads(result) update_frontmatter(str(file_path), { "summary": ai_data.get("summary", ""), "tags": ai_data.get("tags", []), "keywords": ai_data.get("keywords", []), "status": "processed", "processed_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") }) print(f"[DONE] {file_path.name}") except Exception as e: print(f"[ERROR] {file_path.name}: {e}") def main(): parser = argparse.ArgumentParser(description="Process Obsidian inbox files with AI") parser.add_argument("--inbox", type=str, required=True, help="Inbox folder path") parser.add_argument("--provider", type=str, default="ollama", help="ollama or openai") parser.add_argument("--model", type=str, default=None, help="model name") parser.add_argument("--base-url", type=str, default=None, help="API base url") parser.add_argument("--api-key", type=str, default=None, help="API key for openai provider") args = parser.parse_args() if args.provider == "ollama": client = AIClient(provider="ollama", model=args.model or "qwen2.5:7b") else: client = AIClient( provider="openai", base_url=args.base_url or "https://api.openai.com/v1", model=args.model or "gpt-4o-mini", api_key=args.api_key ) inbox_dir = Path(args.inbox) if not inbox_dir.exists(): print(f"[ERROR] Inbox directory not found: {inbox_dir}") return for md_file in inbox_dir.rglob("*.md"): process_file(md_file, client) if __name__ == "__main__": main()脚本中需要导入json和datetime,补上即可:
import json from datetime import datetime运行方式,以本地 Ollama 为例:
cd scripts python process_inbox.py --inbox "../knowledge-base/00 Inbox" --provider ollama --model qwen2.5:7b如果使用在线 API:
cd scripts python process_inbox.py --inbox "../knowledge-base/00 Inbox" --provider openai --base-url "你的API地址" --model "你的模型名" --api-key "你的API密钥"运行结束后,Inbox 中的笔记会自动获得摘要和标签。打开 Obsidian,点击侧边栏文件列表,可以看到每个笔记的元数据都被更新了。
4.5 批量加工:从素材到知识卡片
Inbox 只是临时存放区。经过 AI 摘要后,你需要定期把有价值的素材加工成永久笔记。这一步没必要全部自动化,因为“哪些内容真正重要”仍然需要人来判断。
一个高效流程是这样的:
- 打开 Inbox 中某篇笔记。
- 阅读摘要,判断是否值得深入。
- 如果值得,在
30 Permanent中新建一篇笔记,按“概念 → 论据 → 示例 → 我的看法”结构写卡片。 - 把原始素材链接到这张卡片中,建立双链。
- 在原始素材的 frontmatter 中加上
relates-to字段,指向新的永久笔记。
AI 在这步可以辅助做“概念解释”和“生成类比”。在 Obsidian 中使用第三方 AI 插件或在命令行运行一个简单的 Python 脚本:
# 文件路径:scripts/explain_concept.py # 功能:向模型询问一个概念,要求用通俗语言解释并给出示例 import sys from ai_client import AIClient concept = sys.argv[1] client = AIClient(provider="ollama", model="qwen2.5:7b") messages = [ {"role": "system", "content": "你是一位耐心的老师。请用通俗的语言解释用户提出的概念,给出至少一个生活化类比和一个技术示例。不要输出复杂公式,除非用户要求。"}, {"role": "user", "content": f"请解释:{concept}"} ] print(client.chat(messages, temperature=0.7))用法:
python explain_concept.py "Transformer 中的 attention 机制"输出会是一段几百字的解释。你可以把其中关键部分摘抄到永久笔记中。注意:这类内容不要直接复制粘贴,要经过自己的转述,否则笔记就只是 AI 生成物的堆叠。
4.6 用 Dataview 做知识聚合
当笔记达到一定数量后,不可避免会遇到“我知道自己写过,但想不起来放在哪”的问题。Dataview 可以解决。
在任意笔记中插入以下代码块,可以自动汇总所有7天前到当前状态为processed的笔记:
TABLE summary, tags, file.ctime AS "创建时间" FROM "00 Inbox" WHERE status = "processed" WHERE date(today) - file.ctime <= dur(7 days) SORT file.ctime DESC LIMIT 20这段代码的语义很好理解:
FROM "00 Inbox":限定搜索某个文件夹。WHERE status = "processed":只看已经处理过的笔记。WHERE date(today) - file.ctime <= dur(7 days):只看最近 7 天创建的。SORT file.ctime DESC:按创建时间倒序排列。LIMIT 20:最多显示 20 行。
Dataview 的价值是做“动态汇总”,不需要你手动维护目录索引。今天新建的素材,只要被标记为processed,晚上打开汇总页就能看到。
更进一步,还可以在 Obsidian 首页创建一个“项目总览”笔记:
TABLE type, date, summary FROM "Daily Notes" WHERE type = "daily" SORT date DESC LIMIT 7这样每次打开 Obsidian,都能看到最近 7 天的工作日志摘要。
4.7 AI 周报生成脚本
Daily Note 写了一个月后,逐条翻看效率低。可以用下面的脚本读取某一个时间段的 Daily Notes,把文本内容拼接起来交给 AI 生成周报或月报。
# -*- coding: utf-8 -*- """ 文件路径:scripts/generate_report.py 功能:读取指定日期范围内的 Daily Notes,调用 AI 生成周报/月报 用法:python generate_report.py --daily-dir ../knowledge-base/Daily\ Notes --days 7 """ import argparse import sys from pathlib import Path from datetime import datetime, timedelta from ai_client import AIClient from note_utils import read_note def main(): parser = argparse.ArgumentParser() parser.add_argument("--daily-dir", type=str, required=True, help="Daily Notes folder path") parser.add_argument("--days", type=int, default=7, help="How many days to look back") parser.add_argument("--provider", type=str, default="ollama") parser.add_argument("--model", type=str, default="qwen2.5:7b") args = parser.parse_args() daily_dir = Path(args.daily_dir) cutoff = datetime.now() - timedelta(days=args.days) texts = [] for md_file in daily_dir.glob("*.md"): note_info = read_note(str(md_file)) meta = note_info["frontmatter"] or {} date_str = meta.get("date", "") if not date_str: continue try: file_date = datetime.strptime(date_str, "%Y-%m-%d") except ValueError: continue if file_date >= cutoff: texts.append(f"### {date_str}\n{note_info['content']}") if not texts: print("No daily notes found in the date range. Exit.") return prompt = "以下是用户最近一周的 Daily Notes,请帮用户整理成一份简洁的周报。周报包括:本周完成、正在进展、遇到的阻塞、下周计划。只输出周报正文。\n\n" + "\n".join(texts) client = AIClient(provider=args.provider, model=args.model) messages = [ {"role": "system", "content": "你是知识管理工作流助手,输出格式清晰、内容简洁、不夸大事实。"}, {"role": "user", "content": prompt} ] result = client.chat(messages, temperature=0.2) print(result) if __name__ == "__main__": main()运行示例:
cd scripts python generate_report.py --daily-dir "../knowledge-base/Daily Notes" --days 7生成的周报可以直接复制到 Obsidian 的20 Projects目录下,创建一篇week-review-2025-W51.md。周报不需要每次都完整入库,但关键的行动项记得转成任务。
4.8 从笔记到文章:AI 辅助输出
学习产出的最后一步是把掌握的内容转成文章、技术文档或分享材料。这一步如果从零开始构思,耗时最长;但如果你平时已经把卡片笔记维护好了,输出只是把卡片重新组装。
推荐一种“卡片转文章”的流程:
- 选定一个主题,例如“Transformer 注意力机制”。
- 使用 Dataview 查询所有包含相关标签的笔记:
LIST FROM #深度学习 OR #NLP WHERE status = "processed"- 把筛选后的笔记按顺序排列,确定文章大纲。
- 用 Templater 创建一篇新的文章笔记,模板中包含大纲字段:
--- type: article title: status: draft date: <% tp.date.now("YYYY-MM-DD") %> tags: [] --- ## 文章目标 - ## 大纲 1. ## 引用笔记 - ## 正文 ###- 把相关笔记的关键内容拖进文章草稿,再交给 AI 扩充过渡句和完善结构。
下面提供一个简化版“大纲扩写”脚本,只负责把你写好的大纲展开成初稿:
# -*- coding: utf-8 -*- """ 文件路径:scripts/expand_outline.py 功能:把文章大纲转成完整初稿 """ import sys from ai_client import AIClient outline = sys.stdin.read() client = AIClient(provider="ollama", model="qwen2.5:7b") messages = [ {"role": "system", "content": "你是一位技术写作助手。用户会输入文章大纲。请将大纲扩写为一篇结构完整、语言清晰的技术文章初稿。保留所有观点,不要虚构不存在的细节。"}, {"role": "user", "content": f"大纲如下:\n{outline}"} ] result = client.chat(messages, temperature=0.5) print(result)使用时先把大纲保存到文件中,然后:
type outline.txt | python expand_outline.py > article_draft.md注意:AI 生成的初稿只能当素材,不建议直接发布。它的作用是把“从空白页开始写”的阻塞感打破,让你拿到 80% 的草稿后再人工修改。
4.9 Markdown 转 Word/PDF 输出
Obsidian 自带的“导出 PDF”功能能胜任大部分场景。但如果你需要提交 Word 文档给导师、同事或客户,推荐使用 Pandoc 转换。
安装 Pandoc 后,在 Obsidian 仓库根目录执行:
pandoc "30 Permanent/我的文章.md" -o output.docx如果需要处理图片路径,可以加参数:
pandoc "30 Permanent/我的文章.md" -o output.docx --resource-path=.如果你已经用 Coze、Dify 或其他工作流平台处理过 Markdown 转 Word,其实原理类似。Obsidian 里面只需要“导出 Markdown 原文件 → Pandoc/云端工具转换 → 调整格式”。
5. 常见问题与排查思路
5.1 AI 返回的不是标准 JSON
问题现象:Python 脚本报json.decoder.JSONDecodeError。
可能原因:模型在返回结果中加入了额外说明文字,比如“好的,我已经为你生成了 JSON”之类。
解决思路:
- 在 prompt 中反复强调只输出 JSON。
- 在代码中用正则提取第一个
{到最后一个}之间的内容。 - 对结果做一次去
json标记和空白处理。 - 如果模型不稳定,换一个更稳定的模型或提高
temperature为 0。
建议在process_file函数中加入一个安全的 JSON 解析函数:
import re import json def safe_json_parse(text: str): # 去掉 markdown 代码块标记 text = text.replace("```json", "").replace("```", "").strip() # 匹配第一个花括号到最后一个花括号 match = re.search(r"\{.*\}", text, re.DOTALL) if match: text = match.group(0) return json.loads(text)5.2 Ollama 请求超时或连接被拒绝
问题现象:requests.exceptions.ConnectionError。
排查步骤:
- 确认 Ollama 已启动。
- 在浏览器打开
http://localhost:11434,应返回Ollama is running。 - 确认模型已经拉取成功:
ollama list。 - 如果是远程服务器,确认防火墙端口已开放。
5.3 Obsidian 安装或下载速度过慢
问题现象:官网下载进度条长时间不动。
解决思路:
- 更换网络环境测试。
- 使用可信的国内镜像站下载安装包。
- 不要轻信非官方渠道下发的“绿色版”“破解版”,有安全风险。
5.4 Dataview 查询结果为空
问题现象:插入了 Dataview 代码块,但表格没显示任何数据。
排查步骤:
- 确认代码块语言是
dataview,不是dataviewjs。 - 确认笔记中的 frontmatter 字段名、值是否和查询条件匹配。
- 检查日期字段是否是合法格式。
- 如果使用
WHERE status = "processed",但笔记的status值为空或processed前有空格,就会匹配失败。
5.5 Python 依赖缺失
问题现象:运行脚本时提示ModuleNotFoundError: No module named 'requests'或No module named 'yaml'。
解决思路:
pip install requests pyyaml如果当前环境是 conda 的 base 环境,建议先创建虚拟环境,避免和系统 Python 冲突。
5.6 AI 摘要质量不稳定
问题现象:部分笔记生成的摘要跑偏,或标签与主题无关。
解决思路:
- 降低
temperature,摘要任务建议保持 0~0.2。 - 提供更具体的 prompt,要求“只根据原文提取信息,不要推断”。
- 对超长笔记截断前 2000 字符,跑完主体后再补充后半部分。
- 定期人工抽查,发现偏差就调整 prompt 或换模型。
下面给出一个常见问题速查表:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| AI 返回 JSON 解析失败 | 模型输出多了说明文字 | 用正则提取{}内容,提高 prompt 约束 |
| Ollama 连接失败 | Ollama 未启动或端口被占用 | 检查服务状态和端口,重启 Ollama |
| Obsidian 插件无法安装 | 网络问题或安全模式未关闭 | 检查网络,确认安全模式已关 |
| Dataview 无结果 | 字段名不匹配或日期格式错误 | 检查 frontmatter 字段和查询条件 |
| Python 导入失败 | 虚拟环境未激活或依赖未安装 | 执行pip install requests pyyaml |
| Obsidian 下载太慢 | 网络不稳定 | 更换网络或用国内镜像源 |
| 笔记太多导致脚本运行慢 | 每次调用模型耗时过长 | 增加跳过已处理文件的逻辑,使用本地小模型 |
| AI 生成内容幻觉严重 | 模型太小或 prompt 不清 | 换大模型,或要求“没有依据就说不知道” |
6. 最佳实践与工程建议
6.1 Obsidian 目录设计
很多新手一上来就建几十个文件夹,导致维护成本暴涨。我的建议是:目录层级尽可能浅,用标签和 Dataview 做横向整合,不要用文件夹表达全部分类。
推荐的核心目录:
00 Inbox:所有未经处理的素材。10 Literature:摘录、原文笔记。30 Permanent:经过自己加工后的永久笔记。90 Templates:模板。Daily Notes:日记。
这套结构符合“先捕获→再整理→后内化”的认知顺序,也方便脚本定时处理。
6.2 命名规范
Obsidian 文件名最长建议不超过 80 个字符。中文文件名可以做,但避免特殊符号,比如/、\、:、*、?、"、<、>。如果使用英文文件名,建议用kebab-case(短横线分隔),例如transformer-attention-note.md。
6.3 AI 使用边界
AI 在这套工作流中的角色是“信息处理器”,不是“知识来源”。以下操作适合交给 AI:
- 摘要、打标签、关键词提取。
- 概念解释、类比生成。
- 周报汇总、提纲扩写。
- Markdown 格式转换。
以下操作必须由人完成:
- 判断“这篇笔记是否值得保留”。
- 决定“知识卡片之间是否需要建立链接”。
- 文章的最终审校。
- 包含个人隐私、机密内容的任务,谨慎使用在线 API。
6.4 本地模型优先
如果你的学习笔记涉及个人隐私、真实工作项目、未公开的研究想法,强烈建议优先使用本地模型。Ollama 方式的数据不会离开本机。
在线 API 方案的唯一好处是模型质量更高,对长文理解更好。如果要用,建议通过环境变量管理密钥,不要写死在脚本中:
AI_API_KEY = os.environ.get("AI_API_KEY")6.5 避免插件过多
Obsidian 的插件生态非常丰富,但不是越多越好。每个插件都会增加启动时间、占用资源,并增加未来版本兼容性风险。建议只保留真正进入日常流程的插件:
- 必备:Dataview、Templater、QuickAdd。
- 可选:Calendar、Excalidraw、Pandoc 插件。
- 可尝试:Smart Connections 等 AI 插件,但要意识到这些插件的数据处理方式。
6.6 定期查看跳过文件和错误日志
process_inbox.py目前只是打印日志,没有落盘。实际使用中建议把日志输出到文件:
python process_inbox.py --inbox "../knowledge-base/00 Inbox" --provider ollama 2>&1 | tee process.log这样如果某个文件处理失败,可以在日志中定位原因。
6.7 定期人工清理 Inbox
AI 摘要可以帮你节省整理时间,但它不会判断“这条信息是否需要保留”。建议每周固定一个时间,打开00 Inbox,把已经失去价值的笔记删除或归档到Archive。不要让 Inbox 成为第二个垃圾场。
6.8 周复盘节奏
一套学习产出工作流要运行起来,需要稳定的复盘节奏:
- 每天:写 Daily Note,记录 2~3 条关键输入和输出。
- 每周:运行
generate_report.py,生成周报;检查当前项目进度。 - 每月:Review 这一个月产出的永久笔记数量,看哪些主题投入时间最多。
这个节奏不需要刻意做到完美。哪怕每周只能写 3 条 Daily Note,也比完全依赖“临时回想”好得多。
7. 总结与下一步方向
这套 “AI + Obsidian 智能学习产出工作流” 的核心思路不是用 AI 替代思考,而是把笔记流程中重复、耗时、低价值的环节自动化,让人把精力集中在真正需要判断和创造的部分。
本文带你走完了完整链路:
- 理解了 Obsidian 双向链接、Dataview、Templater、QuickAdd 在工作流中的角色。
- 搭建了本地/在线模型 API 统一客户端。
- 实现了 Inbox 素材的 AI 摘要、标签自动生成。
- 用 Dataview 打通了笔记与动态汇总。
- 用 AI 辅助生成周报和文章初稿。
- 梳理了 Markdown 转 Word 的轻量方案。
下一步你可以继续探索的方向有:
- 接入 RSS 或微信阅读的自动抓取,将外部阅读数据直接进入 Inbox。
- 使用 Smart Connections 插件做语义搜索,在写文章时自动联想相关笔记。
- 用
obsidian-clipper浏览器扩展,把网页一键裁剪成 Markdown 存入 Inbox。 - 把 Python 脚本封装成 Obsidian 的第三方插件,在 Obsidian 内部直接触发。
- 如果团队有研发能力,可以把这套流程升级成服务端应用,用 Dify 或 Coze 搭建可视化工作流,把笔记处理变成团队知识库的一部分。
最后,我在实际使用中最大的感触是:自动化最有价值的地方不是“能节省多少时间”,而是它把每一条被保存下来的信息都推向了“下一步行动”。每一篇笔记进来之后,要么被消化成卡片,要么被输出成文章,要么被判定为不需要保留。当信息流真正流动起来,每天的学习和阅读就不再是无序输入,而会成为一条持续生长的知识输出管线。