记录 在LLM帮助下构建Obsidian-DeepSeek集成插件

MagicNue

00 前言

该项目的构建过程,全面、充分地发挥了Gemini的巨大威力。尤其在人机交互和代码方面的巨大潜力——这还没有用上mcp和rag等拓展,只是单纯地让Gemini为我输出代码,就完成了所有工作。

简单来说,我用Gemini控制台中的Gemini 2.5 Pro Preview 03-25,试图让LLM为我打造一个Obsidian插件。

01 开头、过程和结果

  1. 由于实在无暇去为每一篇博客文章起名字、做摘要、打标签,我想到人工智能可以帮我做到这一点。
  2. 当然不是把我的文章丢进Gemini网站然后让它吐出我想要的东西,这样太麻烦了,需要更简单的方法。
  3. 我初步的想法是制作一个Python脚本,将markdown文件拖入后,脚本会把文章和prompt发送到LLM自动分析内容,为我生成FrontMatter中的标题、日期、摘要和标签。最好就是可以直接插入到markdown文件中。
  4. 但后来我发现它可以为我打造一个Obsidian插件,直接将LLM集成到软件,那么除了上面的内容外还能够为我分析文章内容或者做别的什么事情,总之就是打造成了一个相当强悍的软件。
  5. 和之前的开发过程没什么不同——我几乎一行代码都没敲。Obsidian插件似乎使用的是.ts后缀的文件和typescript语言。我没有去管代码部分,也没有兴趣去管。我只负责把需求告诉LLM,把LLM吐出的代码复制粘贴进项目,一键npm run build编译完丢进插件运行,检测结果再让LLM修改就好了。

最后的效果相当令人满意。
LLM把这个项目称为:Obsidian-DeepSeek 集成

成果

03 Obsidian-DeepSeek 集成插件:构建历程与成果总结

1. 项目目的与用途

动机:

用户最初的需求是创建一个简单的 Obsidian 模板,用于自动填充笔记的 title (文件名) 和 date (修改时间)。然而,很快用户产生了更进一步的想法:希望实现更高级的自动化,利用 AI 能力自动为笔记添加相关标签 (Tags) 和生成内容摘要 (Excerpt)。

目标演变:

在探讨现有 AI 插件(如 Text Generator)后,用户认为其不够理想,决定自行构建一个定制化的 Obsidian 插件。核心目标转变为:创建一个能与 DeepSeek 大语言模型 API 深度集成的插件,提供灵活、可控的文本生成能力,直接在 Obsidian 编辑器内完成操作。

最终用途:

该插件旨在成为 Obsidian 用户利用 DeepSeek AI 进行笔记辅助创作的工具。用户可以通过配置 API 信息和自定义 Prompt 模板,实现多样化的功能,例如:

  • 基于选中文本或全文内容进行续写、总结、翻译、问答等。
  • 根据特定指令生成符合要求的文本内容。
  • 通过快捷键或命令面板快速调用 AI 能力,提升笔记效率。

2. 项目框架

该 Obsidian 插件 (“DeepSeek Integration”) 最终形成的框架包含以下核心组件:

  • 基础结构:
    • 遵循 Obsidian 插件标准,包含 main.ts (主逻辑)、settings.ts (设置定义与模板渲染)、manifest.json (插件清单)。
  • 设置系统:
    • 图形用户界面 (GUI): 通过 PluginSettingTab 实现,提供结构化的设置选项。
    • API 配置: 输入框用于配置 DeepSeek API 地址、API 密钥、模型名称。
    • 连接测试: 按钮调用实际 API (非流式 /chat/completions) 以验证配置有效性。
    • 流式模式开关: Toggle 组件允许用户启用/禁用流式响应。
    • Prompt 模板管理:
      • 支持存储多个 Prompt 模板 (包含名称和内容)。
      • 提供下拉菜单选择当前激活的模板。
      • 通过弹窗 (Modal) 实现模板的添加、编辑和删除功能。
    • 本地化: 设置界面的标签、描述和提示信息支持中文显示。
    • 数据持久化: 使用 Obsidian 的 loadData()saveData() 存取设置。
  • 核心命令:
    • 生成文本 (generate-text-with-deepseek):
      • 注册为 editorCallback,确保在编辑器环境运行。
      • 通过命令面板或快捷键触发。
      • 智能上下文处理:优先使用选中文本 (selection),若无选区则使用笔记全文 (content) 作为主要输入。
      • 加载当前激活的 Prompt 模板。
      • 调用 simpleTemplateRender 函数,根据选区情况和模板结构,动态生成最终发送给 API 的 finalPrompt
      • 根据设置调用 DeepSeek API (/v1/chat/completions),支持流式 (fetch + SSE)非流式 (requestUrl) 请求。
      • 将 API 返回的文本插入/替换到编辑器光标位置。
    • 中止生成 (abort-deepseek-stream):
      • 用于中断正在进行的流式 API 请求 (AbortController)。
    • 打开设置 (open-deepseek-settings):
      • 方便用户快速访问插件设置页面。
  • 模板渲染:
    • simpleTemplateRender 函数:一个基础的渲染器,支持变量替换 ({{key}}) 和简单的条件判断 ({{#if key}}...{{/if}}),用于根据上下文动态构建 Prompt。

3. 项目的工作流程

用户与插件交互的典型流程如下:

  1. 首次配置: 安装插件后,进入 Obsidian 设置 -> DeepSeek 集成设置。
    • 输入有效的 DeepSeek API 地址、密钥和模型名称。
    • 点击“测试连接”按钮,确认配置无误。
    • 选择是否启用“流式模式”。
    • 检查、编辑或添加所需的 Prompt 模板,并选择一个作为“当前模板”。
  2. 日常使用:
    • (可选) 选中内容: 如果只想让 AI 处理部分文本,用光标选中该部分。
    • 触发命令:
      • 方式一 (推荐): 按下为“使用 DeepSeek 生成文本”命令设置的快捷键
      • 方式二:Ctrl/Cmd+P 打开命令面板,搜索并选择“使用 DeepSeek 生成文本”。
    • 插件执行:
      • 插件检测是否有选中文本。
      • 根据检测结果准备 templateData (仅包含 selection 或仅包含 content)。
      • 加载当前激活的 Prompt 模板内容。
      • 使用 simpleTemplateRender 结合 templateData 和模板,生成 finalPrompt
      • 根据“流式模式”设置,向 DeepSeek API 发送请求。
      • 流式: 插件逐块接收响应,并实时更新到编辑器光标处。用户可随时通过“中止 DeepSeek 生成”命令或快捷键停止。
      • 非流式: 插件等待完整响应后,一次性将结果插入/替换到编辑器光标处。
    • 查看结果: 生成的文本出现在笔记中。

4. 项目的构建流程(LLM 协作视角)

这次插件的构建是一个典型的人机协作、迭代开发的过程,关键节点和互动如下:

  1. 需求明确与方案选择:
    • 用户: 提出从模板到 AI 自动化的需求。
    • LLM: 介绍现有插件方案。
    • 用户: 决定自建插件,明确集成 DeepSeek API 的目标。
  2. 基础框架搭建:
    • 用户: 确认具备 Node/npm 环境。
    • LLM: 指导使用官方模板 git clonenpm install,修改 manifest.json,以及如何在 Obsidian 中加载和启用插件。
  3. 设置界面开发:
    • 用户: 要求实现配置 API、模型和测试连接的设置页。
    • LLM: 提供 settings.ts (接口与默认值) 和 main.tsPluginSettingTab 的实现代码,包含输入框和按钮布局。
    • 用户: 发现测试连接仅为占位符,即使模型错误也显示成功。
    • LLM: 修正代码,在测试连接中加入实际的 requestUrl API 调用,并进行错误处理和状态反馈。
  4. 核心命令实现:
    • 用户: 要求实现点击按钮或命令,读取文档信息并调用 LLM 在光标处生成文本。
    • LLM: 提供 addCommandeditorCallback 的代码,实现获取编辑器上下文 (selection, content, filename),调用 API (requestUrl 非流式),并将结果插入编辑器 (editor.replaceSelection)。
  5. 流式功能添加:
    • 用户: 要求新增 Stream 模式选项。
    • LLM:
      • 修改 settings.ts 添加 useStream 选项。
      • 更新设置界面添加 Toggle 开关。
      • 引入 fetch API 和 SSE (Server-Sent Events) 解析逻辑来处理流式响应。
      • 实现 handleStreamRequest 方法,包含实时更新编辑器 (editor.replaceRange)更新光标位置
      • 引入 AbortController 和对应的中止命令 (abort-deepseek-stream) 来控制流式请求。
      • 提供统一的错误处理函数 handleApiError
  6. Prompt 管理功能:
    • 用户: 要求支持选择、编辑和切换多个 Prompt 模板。
    • LLM:
      • 修改 settings.ts,将 promptTemplate 字符串改为 prompts: PromptTemplate[] 数组,并添加 activePromptName 字段。
      • 在设置界面使用 Dropdown 让用户选择激活模板。
      • 创建 PromptEditModal 类 (继承 Modal),用于添加和编辑模板名称与内容。
      • 在设置界面添加“添加新模板”按钮和模板列表(含编辑、删除按钮),并实现相应的逻辑(增删改查、重名检查、默认模板处理)。
      • 修改核心命令逻辑,使其加载并使用当前激活的模板。
  7. 上下文处理逻辑澄清与优化:
    • 用户:{{selection}}{{content}} 如何根据选区情况传递给 LLM 产生疑问,担心两者会同时发送。
    • LLM: 详细解释了 main.ts根据 currentSelection 是否为空来选择性填充 templateData.selectiontemplateData.content 的代码逻辑,并阐述了 simpleTemplateRender 如何配合 {{#if ...}} 条件块来实现最终只发送相关上下文给 LLM。
    • 用户: 确认理解该机制,并提出/确认简化模板的可行性。
  8. UI 本地化:
    • 用户: 要求将插件设置界面的标签、按钮、提示等改为中文。
    • LLM: 提供更新后的 main.ts 代码,将所有面向用户的硬编码英文字符串替换为中文。

结果: 通过这次高度互动和迭代的过程,我们成功构建了一个功能相对完善、满足用户特定需求的 Obsidian-DeepSeek 集成插件。该插件具备配置灵活、支持流式输出、可管理 Prompt 模板,并能根据用户是否选中内容智能调整发送给 AI 的上下文信息,最终将结果直接输出到 Obsidian 笔记中。

04 项目开源

我之后会把项目开源,放到Github上。Obsidian插件也会放到插件市场。
只要我没忘掉,嗯。(冒汗)

与LLM的对话记录(私人):https://aistudio.google.com/prompts/1EG6Envg0F0x3daVCiQXKdAJnp-LcwL3q

  • Title: 记录 在LLM帮助下构建Obsidian-DeepSeek集成插件
  • Author: MagicNue
  • Created at : 2025-04-26 00:00:00
  • Updated at : 2025-05-19 10:52:58
  • Link: https://magicnue.top/2025_/记录 在LLM帮助下构建Obsidian-DeepSeek集成插件/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments