Khoj 的 Notion 集成:从连接工作区到本地检索的完整实现解析

Khoj 的 Notion 集成:从连接工作区到本地检索的完整实现解析 Khoj 的 Notion 集成从连接工作区到本地检索的完整实现解析【免费下载链接】khojYour AI second brain. Self-hostable. Get answers from the web or your docs. Build custom agents, schedule automations, do deep research. Turn any online or local LLM into your personal, autonomous AI (gpt, claude, gemini, llama, qwen, mistral). Get started - free.项目地址: https://gitcode.com/GitHub_Trending/kh/khoj本篇围绕 Khoj 的 Notion 集成Notion Integration展开它让你可以直接搜索、聊天问答自己 Notion 工作区里的笔记。读完你将掌握两种接入方式云端 OAuth 一键授权与自托管 API Key 手动配置的完整操作步骤并能从源码层面理解 Khoj 如何将 Notion 页面拉取、分块、写入向量库最终进入统一的检索与对话流程。功能定位把 Notion 变成可检索的数据源Notion 是人们用来记笔记、协作的知识平台。Khoj 的 Notion 集成会把你的 Notion 工作区作为一个内容源data source接入Khoj 通过 Notion API 拉取你有权限访问的页面将内容拆分为可检索的条目Entry生成嵌入embeddings后存入本地数据库。此后无论是 Web 端的搜索框还是对话chat你的 Notion 笔记都会与本地文档、GitHub 代码等数据源一起参与召回。接入方式有两种云端Khoj Cloud登录app.khoj.dev后在 Settings 页面连接你的 Notion 工作区走的是 OAuth 授权流程自托管Self-Hosted在 Notion 侧创建一个名为 Khoj 的 integration 并拿到 API Key手动填入本地设置页。两种方式的最终落点相同数据库中的NotionConfig记录 一次后台索引任务。下面先给出自托管的完整操作步骤再逐层拆解实现。自托管接入步骤可复制操作文档给出的自托管流程如下每一步都对应了明确的验证点登录 Notion进入My Integrations页面创建一个名为Khoj的新 integration复制生成的API Keyinternal integration secret形如ntn_...或secret_...。在 Notion 中把你希望被索引的workspace工作区共享给刚创建的 Khoj integration——这一步决定 Khoj 能“看见”哪些页面未共享的页面不会被拉取。打开本地 Khoj 的设置页默认地址http://localhost:42110/settings#notion在 Notion 配置项中粘贴上一步的 API Key点击Save。在设置页点击Configure触发对 Notion 工作区的索引。完成后即可开始搜索与聊天。文档同时提醒请确保已经配置好 聊天设置即选择并配置好一个对话模型否则索引完成也无法发起 chat。从源码结构看Save 与 Configure 两步分别对应两个后端动作Save 把 token 写入NotionConfigConfigure或在保存 token 的同时以后台任务形式调用configure_content(user, {}, False, SearchType.Notion)只索引 Notion 这一种内容类型避免重复处理其他数据源。连接凭证如何存储与读写数据模型Notion 凭证存储在 Django 模型 NotionConfig 中class NotionConfig(DbBaseModel): token models.CharField(max_length200) user models.ForeignKey(KhojUser, on_deletemodels.CASCADE)要点token最大长度 200 字符每个用户一条记录随用户级联删除token 是 Notion API 的 Bearer 凭证后续所有 Notion API 请求都携带它。数据库层的读写封装在 src/khoj/database/adapters/init.py 中set_notion_config(token, user)负责写入get_user_notion_config(user)负责读取当前用户的配置。设置页对应的 API 端点设置页背后的 REST 端点定义在 src/khoj/routers/api_content.py 与 set_content_notionGET /api/content/notion读取当前用户配置把NotionContentConfig(token...)定义见 src/khoj/utils/rawconfig.py其中唯一字段就是token: str序列化为 JSON 返回给前端未配置时 token 为空串POST /api/content/notion接收前端提交的NotionContentConfig调用set_notion_config持久化若 token 非空则立即通过background_tasks触发configure_content(user, {}, False, SearchType.Notion)——这也是设置页点击 Save 后索引自动开始的原因接口本身不阻塞等待索引完成。因此自托管路径完全不需要额外环境变量只要用户在设置页填入有效 API Key索引流程就能走通。云端 OAuth 授权流程源码视角云端部署下用户无需手动管理 API Key。相关实现集中在 src/khoj/routers/notion.py依赖三个环境变量NOTION_OAUTH_CLIENT_ID/NOTION_OAUTH_CLIENT_SECRETNotion OAuth 应用的客户端凭证NOTION_REDIRECT_URI授权回调地址。流程分两半1. 生成授权链接。get_notion_auth_url 在三个环境变量齐全时构造https://api.notion.com/v1/oauth/authorize链接response_typecodestate参数携带当前用户 UUID该 URL 随用户配置数据notion_oauth_url字段下发到前端设置页。若任一环境变量缺失则返回None前端自然不会展示 OAuth 入口——这也是自托管环境下默认走 API Key 手动配置路径的原因。2. 回调换 token。GET /api/auth/callback即 notion_auth_callback处理授权回跳校验code与state参数并用会话中已认证的用户替代 state 传参来识别身份同时校验state user.uuid作为 CSRF 防护不匹配则返回 400删除该用户旧的NotionConfig再以Basic base64(client_id:client_secret)认证头向https://api.notion.com/v1/oauth/token提交grant_typeauthorization_code换取access_token将access_token写入NotionConfig记录 owner / workspace_id / workspace_name / bot_id 日志通过background_tasks异步执行configure_content(user, {}, False, SearchType.Notion)开始索引随后 302 跳回设置页config_page。可以推断OAuth 拿到的 token 与自托管手填的 internal integration token 在后续流程中是等价的二者都只作为 Bearer 凭证使用因此索引与检索代码完全不感知授权方式差异。索引流水线Notion 页面如何变成可检索条目索引核心是 src/khoj/processor/content/notion/notion_to_entries.py 中的NotionToEntries继承自TextToEntries。入口由 configure_content 调度当客户端没有随请求发送任何文档时它从数据库取出该用户的NotionConfig并调用text_search.setup(NotionToEntries, None, regenerate..., useruser, confignotion_config)完成拉取、分块与嵌入更新。初始化与 API 会话构造器L48-L80做三件事建立requests.Session请求头固定为Authorization: Bearer token与Notion-Version: 2022-02-22定义不支持的块类型bookmark、divider、child_database、template、callout、unsupported——命中这些类型时返回空字符串即被静默跳过定义展示型块类型paragraph、heading_1~3、bulleted/numbered_list_item、to_do、toggle、child_page 等命中时文本前后补换行保证分块后的语义边界。全量拉取与分页process()L82-L116通过 Notion 的 search 端点遍历工作区while True: result self.session.post( https://api.notion.com/v1/search, jsonself.body_params, # 初始 {page_size: 100} ).json() responses.append(result) if not result.get(has_more, False): break else: self.body_params.update({start_cursor: result[next_cursor]})即每页 100 条、用start_cursor翻页直至has_more为 false。对每条结果object database的直接跳过源码中留有TODO: Handle databases注释说明数据库型内容当前版本不作为条目索引object page的交给process_page()处理。页面分块策略process_page()L118-L174按块block遍历页面内容分块规则是“标题即边界”遇到heading_1/2/3块时把此前累积的raw_content先落成一个Entry并更新当前 heading其他块若已有 heading 上下文会先通过process_heading()写入b标题/b作为上下文前缀再追加块文本富文本链接被渲染为a href...文本/a保留锚点信息若块带子节点has_children递归调用get_block_children()拉取/v1/blocks/{block_id}/children并继续拼接实现嵌套内容的展开。每个Entry的file字段是页面的 Notion URL即结果中“来源文件”展示的是该页面链接heading为页面标题。页面标题的提取get_page_content按title → Title → Name → Page → Event的顺序在页面属性中回退查找找不到则记 warning 并将该页跳过。切分与入库拉取完成后L114-L116先经TextToEntries.split_entries_by_max_tokens(current_entries, max_tokens256)将超长条目切成不超过 256 token 的片段再调用update_entries_with_ids()内部以DbEntry.EntryType.NOTION/DbEntry.EntrySource.NOTION及keycompiled执行增量的嵌入更新——新增内容补嵌入、失效内容删除旧嵌入重复点击 Configure 不会产生重复条目。这意味着 Notion 内容在数据库中的身份标记是统一的EntryType.NOTION与 Markdown、Org、PDF 等来源并列。检索与对话如何消费 Notion 数据索引完成后Notion 条目进入统一的检索体系内容类型枚举在 src/khoj/utils/config.py 中声明为SearchType.Notion notion检索器通过 src/khoj/search_type/text_search.py 中的映射表把SearchType.Notion关联到EntryType.NOTION因此指定 notion 类型检索时只召回 Notion 来源条目all类型则与其他来源混合召回设置页还会依据 enabled_content_sources 判断用户是否已启用 notion 数据源基于该用户 Entry 表中出现过的 file source用于前端展示当前已连接的数据源状态。至此一篇 Notion 页面经历的完整链路是Notion API 拉取 → 按标题分块并保留 heading 上下文 → 256 token 切分 → 生成/更新向量 → 以 EntryType.NOTION 参与搜索与 chat 召回。边界与注意事项结合源码可以确认以下限制配置前值得了解Database 类型内容暂不索引search 端点返回的database对象被显式跳过源码注释为 TODONotion 数据库视图中的内容需要落到普通页面才可被检索部分块类型被忽略bookmark、divider、child_database、template、callout 等类型不产生文本页面上的 callout 提示等内容不会进入检索语料页面必须有可识别标题属性中找不到title/Title/Name/Page/Event任一字段时该页被跳过见 get_page_content权限边界由 Notion 侧决定Khoj 只能看到已共享给 integration 的 workspace撤销共享后下次索引即不再包含对应页面索引是增量且幂等的基于compiled内容比对做增删update_entries_with_ids可放心重复点击 Configure 触发同步。参考路径汇总数据源文档 notion_integration.md、索引实现 notion_to_entries.py、内容 API api_content.py、OAuth 路由 notion.py、数据模型 models/init.py、调度逻辑 helpers.py。【免费下载链接】khojYour AI second brain. Self-hostable. Get answers from the web or your docs. Build custom agents, schedule automations, do deep research. Turn any online or local LLM into your personal, autonomous AI (gpt, claude, gemini, llama, qwen, mistral). Get started - free.项目地址: https://gitcode.com/GitHub_Trending/kh/khoj创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考