人工智能AI 应用大模型RAG后端AI Agent【免费下载链接】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 仓库中真实存在的长文样本tests/data/markdown/undergraduation.markdownPaul Graham 的经典随笔《Undergraduation》展开完整讲解 Khoj 将长篇 Markdown 笔记转化为可检索、可对话的向量化知识条目的完整链路。读完本文你将掌握 Khoj 的 Markdown 内容管线如何按标题结构递归切分、如何按 token 上限做二次分割、如何为每个条目生成带行号溯源能力的 URI以及如何通过哈希去重实现增量索引并能够将这套方法论直接应用到自己的个人知识库建设中。一、样本文档在仓库中的角色与内容概览undergraduation.markdown位于 tests/data/markdown/ 目录同目录下还有what_i_worked_on.markdown、having_kids.markdown、how_y_combinator_started.markdown等一批 Paul Graham 随笔以及一份用于解析测试的 main_readme.md。从仓库结构可以推断这批文件是Khoj Markdown 解析器的真实测试语料它们形态各异——有纯 H1 长文如本篇、有嵌套多级标题的文档如main_readme.md恰好覆盖了不同 Markdown 结构对索引管线带来的挑战。从内容上看《Undergraduation》是一篇约 160 行的长篇随笔发布于 2005 年讨论计算机专业本科生在大学期间如何成长为优秀的程序员。它的 Markdown 结构极具代表性只有一个顶级标题# Undergraduation正文用**Hacking**、**Math**、**Everything**、**Jobs**、**Grad School**、**Notes**等粗体行充当小节标题而非##二级标题全文约 1100 个英文单词远超 256 个 token 的索引上限。这种有且仅有一个 H1、内部全靠粗体分段的文档形态在真实个人笔记与博客归档中非常常见。而 Khoj 的 MarkdownToEntries 正是专门为这类文档设计的解析器接下来我们沿着它的调用链逐层拆解。二、索引入口从上传文件到 Markdown 条目提取Khoj 的 Markdown 内容索引并不是零散散落在各处的逻辑而是一条清晰的三段式管线其入口在 api_content.py 的 indexer 接口文件归类上传的文件按扩展名归类到index_files字典其中markdown键专门收集 Markdown 文件内容映射关系为文件名 → 文件文本进入配置器组装成IndexerInput后调用 configure_content。其中 Markdown 分支的代码非常简洁# 摘自 src/khoj/routers/helpers.py if (search_type state.SearchType.All.value or search_type state.SearchType.Markdown.value) and files.get(markdown): logger.info( Setting up search for markdown notes) text_search.setup(MarkdownToEntries, files.get(markdown), regenerateregenerate, useruser)统一处理入口text_search.setup 最终调用MarkdownToEntries().process(filesfiles, useruser, regenerateregenerate)返回新增条目数 / 删除条目数两个统计值。也就是说无论你是通过 Web 上传、桌面客户端同步还是未来通过 API 推送Markdown 文件最终都会汇聚到同一个处理类MarkdownToEntries。该类的process()方法见 markdown_to_entries.py内部做三件事提取条目 → 按 token 切分 → 增量更新向量库。其中max_tokens 256是本管线的关键常量下面逐一展开。三、按标题结构递归切分Heading 祖先链机制MarkdownToEntries.extract_markdown_entries源码位置负责把文件名 → 文本的字典逐文件交给process_single_markdown_file处理。这是整个解析器的核心逻辑可以概括为两条规则规则一内容很小或没有更深层标题时整段存为一个条目。判断条件如下if len(TextToEntries.tokenizer(markdown_content_with_ancestry)) max_tokens or not re.search( rf^#{{{len(ancestry) 1},}}\s, markdown_content, flagsre.MULTILINE ): # 保存为单个 entry记录起始行号注意这里的tokenizer在 text_to_entries.py 中实现本质就是text.split()——按空白分词。因此max_tokens256实际含义是256 个以空白分隔的单词而非严格的语言模型 token 数。这是一个值得注意的实现细节Khoj 用单词数近似 token 数换取解析速度与确定性。规则二存在更深层标题时按标题级别递归拆分。拆分通过正则(?[#]{N} .?)找到当前层级的下一个标题把内容切成多个 section然后带着标题祖先链ancestry: Dict[int, str]键为标题级别值为标题文本递归进入下一层。每个 section 记录其在原文件中的起始行号start_line行号指向标题行本身。那么像undergraduation.markdown这种只有 H1、内部全是**Hacking**这类粗体文本的文档会怎样答案是它命中规则一——正则^#{2,}\s在全文找不到任何二级标题因此整个文档会被当作一个原始条目raw为全文保存下来再进入下一阶段的 token 级切分。这正是该测试语料的工程价值所在它验证并覆盖了无子标题长文这一分支路径。同一目录下的main_readme.md则因为存在## Dependencies、## Installation等多级嵌套标题走的是递归拆分路径对应测试 test_line_number_tracking_in_recursive_split。四、Token 级二次切分长文如何被拆成可嵌入的块《Undergraduation》约 1100 词远超 256 词上限单条目无法直接交给 embedding 模型。于是process()紧接着调用split_entries_by_max_tokens源码位置用 LangChain 的RecursiveCharacterTextSplitter做二次切分。核心参数值得逐条说明参数取值作用chunk_sizemax_tokens默认 256每个块的单词数上限separators[\n\n, \n, !, ?, ., , \t, ]切分优先级段落 换行 感叹句 问句 句号 空格 字符先按粗粒度切切不动再降级keep_separatorTrue保留分隔符避免句子被拦腰截断chunk_overlap0块之间不重叠配合增量哈希去重切分后除第一个块外后续每个块都会前置拼上原条目 heading 的最后 100 个字符作为上下文前缀snipped_heading entry.heading[-100:]因为对于大文档这条内容来自哪个文件/标题对检索模型至关重要。随后通过remove_long_words丢弃超过 500 字符的超长单词防止 URL 或 base64 破坏块质量并通过clean_field清除\0等非法字符。对《Undergraduation》而言一次切分大约会产生 45 个 256 词以内的块每块都携带# tests/data/markdown/undergraduation.markdown这个文件级前缀详见下一节从而保证块与源文档的归属关系在向量检索中不会丢失。五、Entry 生成与行号溯源每个知识块都有档案切分完成后convert_markdown_entries_to_maps源码位置把原始字符串组装成结构化的Entry对象。这里有两个关键设计1. 编译文本以文件名作为顶级标题。每个 entry 的compiled字段会拼接# {文件名}\n前缀使得检索结果来自哪个文件这一信息直接进入 embedding 编码。heading 为空的纯文本段落前缀退化为仅含文件名一行。2. URI 携带精确行号。对本地文件URI 格式为file:///data/web/disk1/git_repo/GitHub_Trending/kh/khoj/tests/data/markdown/undergraduation.markdown#line1行号从条目在源文件中的实际起始行计算对以http(s)://开头的文件Khoj 也支持直接索引 URL则保留 URL 本身。切分器在生成子块时还会通过在 raw 文本中查找子块的实际位置来重新计算#line行号见 text_to_entries.py 中 line 84-109保证每个切分块的行号都指向真实内容而非块首。这一设计在测试中被严格验证test_line_number_tracking_in_recursive_split 会逐条断言URI 中的行号指向的文件行必须能匹配该 entryraw的首个非标题行。这保证了你在 Khoj 中点开检索结果时能直接跳转到笔记原文中的准确位置——这正是AI 第二大脑类工具最核心的溯源体验。六、增量索引与向量化哈希去重驱动的知识同步最后一步update_embeddings源码位置解决文件更新后如何只重建变化的部分哈希建档对每个条目的compiled字段做 MD5 哈希hash_func见 text_to_entries.py并按文件聚合差异识别查询数据库已有哈希hashes_to_process hashes_for_file - existing_entry_hashes只有新增部分才生成 embeddingregenerateTrue时则先清空该类型全部旧条目批量入库embedding 按min(200, num)批量写入DbEntry同时记录file_typemarkdown、file_sourcecomputer见 markdown_to_entries.py。DbEntry.EntryType.MARKDOWN的定义在 database/models反向清理对每个文件将数据库中已不存在于当前哈希集合的条目删除若客户端传入的某文件内容为空字符串则视为删除标记整文件条目连同文件对象一并清除日期索引顺带用DateFilter抽取条目中的日期写入EntryDates为后续按日期过滤检索date_filter铺路。对《Undergraduation》这类静态随笔首次索引会全量入库之后即使你反复重新同步同一文件哈希相同的块会被直接跳过实现零成本幂等。新增一个段落时只有受影响的块会被重新向量化。七、从测试语料看工程启示如何为个人知识库准备 Markdowntests/data/markdown/这批语料连同 test_markdown_to_entries.py 中从无标题、单标题、多标题到非递增标题级别的全覆盖测试揭示了为知识库工具准备笔记的三条实用建议善用标题层级Khoj 会以标题为锚点组织条目并保留祖先链。用规范的#/##/###层级而非粗体替代组织长文能让检索返回更精准的段落级命中且行号定位更精确。控制单段粒度解析以 256 词为块上限段落切分优先于句子切分。因此一段一意的写作习惯天然有利于被完整索引过长的段落会被强制在句号处切开。合理处理废弃内容同步时把已删除文件的内容置空即可触发 Khoj 的整文件清理机制无需额外调用删除接口。结语从tests/data/markdown/undergraduation.markdown这一篇长文样本出发我们完整走通了 Khoj 的 Markdown 索引链路入口configure_content → text_search.setup、标题递归切分与祖先链、RecursiveCharacterTextSplitter的 token 级切分、带#line行号溯源的 Entry 生成以及 MD5 哈希驱动的增量向量化。这套管线对无子标题长文多级嵌套文档URL 文件等形态各异的 Markdown 都有明确的处理分支并配有专门的解析测试tests/test_markdown_to_entries.py与真实语料tests/data/markdown/持续验证。理解了这些内部机制你在规划自己的笔记结构、批量导入历史文档时就能让 Khoj 的检索与对话能力发挥出最大价值。赞分享人工智能AI 应用大模型RAG后端AI Agent【免费下载链接】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 的 Markdown 知识库索引实战以 having_kids.markdown 为样例理解标题切分、嵌入与 Agent 检索Khoj 的 Markdown 知识库索引实战以 having_kids.markdown 为样例理解标题切分、嵌入与 Agent 检索 导读 本文以 kho人工智能AI 应用大模型RAG后端AI AgentNew Beginnings以 id 索引的 Markdown 内容基准测试样本解析New Beginnings以 id 索引的 Markdown 内容基准测试样本解析 导读 本文以 Gatsby 仓库中 benchmarks/markdo前端静态站点Web框架LocalGPT索引管道终极指南从文档到向量化的完整流程解析LocalGPT索引管道终极指南从文档到向量化的完整流程解析 LocalGPT是一款能让你在本地设备上与文档对话的强大工具所有数据处理都在本地完成确保10AI 应用RAG大模型NLP后端前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考