ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Contributing to langchaingo

Contributing to langchaingo Contributing to langchaingo【免费下载链接】langchaingoLangChain for Go, the easiest way to write LLM-based programs in Go项目地址: https://gitcode.com/GitHub_Trending/la/langchaingoFirst off, thanks for taking the time to contribute! ❤️ All types of contributions are encouraged and valued. See the Table of Contents for different ways to help and details about how this project handles them. ...And if you like the project, but just dont have time to contribute, thats fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:Star the projectTweet about it ...可以看到第一个 chunk 保留了顶层标题 # Contributing to langchaingo 与引言段落引用块被整体保留并以前缀 还原 Markdown 语义每个 chunk 之间由 --- 分隔。 ## 二、MarkdownTextSplitter 的核心机制 ### 2.1 统一接口 所有分割器都实现 [TextSplitter](https://link.gitcode.com/i/d164aaf1579fc056534b1bc02897aed0) 接口只有一个方法 go type TextSplitter interface { SplitText(text string) ([]string, error) }MarkdownTextSplitter在 markdown_splitter.go 中定义结构体字段与构造函数NewMarkdownTextSplitter一一对应type MarkdownTextSplitter struct { ChunkSize int ChunkOverlap int SecondSplitter TextSplitter CodeBlocks bool ReferenceLinks bool HeadingHierarchy bool JoinTableRows bool LenFunc func(string) int }2.2 解析与逐块分派SplitTextmarkdown_splitter.go的流程分两步使用gitlab.com/golang-commonmark/markdown解析器把 Markdown 源码解析成 token 流markdown.New(markdown.XHTMLOutput(true))构造markdownContext持有游标startAt/endAt、token 列表、分块参数、当前标题栈等状态调用splitText()逐 token 扫描。主循环markdown_splitter.go是一个典型的按 Markdown 块类型分派的switchToken 类型处理函数对应 Markdown 元素HeadingOpenonMDHeaderH1~H6 标题TableOpenonMDTable表格ParagraphOpenonMDParagraph段落BlockquoteOpenonMDQuote引用块BulletListOpenonMDBulletList无序列表OrderedListOpenonMDOrderedList有序列表ListItemOpenonMDListItem列表项可能嵌套子列表CodeBlockonMDCodeBlock缩进代码块FenceonMDFence围栏代码块HronMDHr分割线---其他跳到对应关闭标签之后跳过每个处理函数先通过indexOfCloseTagmarkdown_splitter.go找到与当前开始标签配对的关闭标签位置该辅助函数用反射表closeTypes维护开始类型→关闭类型的映射并正确处理嵌套计数再针对该块类型做语义化切割最后把产出的小片段通过joinSnippet汇入当前块。2.3 标题栈chunk 的前缀标题从哪来onMDHeadermarkdown_splitter.go是这套机制的核心。它从 token 中取出HLevel与标题文本构造形如## Second header: h2的标题行同时维护一个hTitleStack若开启HeadingHierarchy对应选项WithHeadingHierarchy当前块会被前缀上从顶层到当前层级的全部标题用换行连接、忽略空层级这正是样例中多个 chunk 都带有多级标题前缀如# Fourth header: h1\n## Fifth header: h2\n#### Sixth header: h4的原因每个标题出现时都会先applyToChunks()触发一次封块因此标题天然成为 chunk 的边界——新标题总是开启新块并把标题作为该块及后续块的前缀。applyToChunksmarkdown_splitter.go负责最终成块若当前块长度未超过ChunkSize ChunkOverlap直接作为一个 chunk若超过则交给SecondSplitter二次切分默认是 NewRecursiveCharacter分隔符依次为\n\n、\n、最终为每个 chunk 前缀标题且通过hTitlePrepended标志保证标题只被写入一次。三、从样例看输出规律chunk 边界与标题前缀对照 example_markdown_header_512.md 的实际输出可以总结出以下可复现的规律3.1 标题是硬边界样例中每一个##/###/####标题都开启一个新的 chunk。例如Reporting Bugs一节#### Before Submitting a Bug Report标题多次出现每次都被单独成块且新块会携带当前完整的标题层级前缀#### Before Submitting a Bug Report - Make sure that you are using the latest version.3.2 同级标题连续出现时合并到相邻块连续出现的标题如### Reporting Bugs后紧跟#### Before Submitting a Bug Report会被合并在同一个块内体现为标题即内容前缀的设计### Reporting Bugs #### Before Submitting a Bug Report A good bug report shouldnt leave others needing to chase you up for more information. ...3.3 引用块整体保留文档中的引用如开篇的支持项目的方式、I Have a Question前的提示、Legal Notice被完整保留且每行以前缀还原。这在onMDQuotemarkdown_splitter.go中通过递归克隆子上下文并把每个子 chunk 用formatWithIndent(chunk, )缩进实现。3.4 多级列表保序保缩进样例中的目录Table of Contents是一个三层嵌套的无序列表。onMDListItemmarkdown_splitter.go递归处理子列表indentLevel控制缩进二级及以下列表项会附加两个空格的前缀。因此输出中的层级缩进与原文一致## Table of Contents - [I Want To Contribute](#i-want-to-contribute) - [Reporting Bugs](#reporting-bugs) - [Before Submitting a Bug Report](#before-submitting-a-bug-report) - [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report)3.5 长块触发二次分割当段落较长、超出 512 字符时applyToChunks会把当前块交给SecondSplitter再次切分切分后每个子块仍会前缀标题。这也是内容充实度不缩水的保障不会因为块超长而丢弃信息。四、参数配置全解析MarkdownTextSplitter的所有行为都由 options.go 中的函数式选项控制。下表汇总全部相关参数及其默认值默认值定义于 token_splitter.go 与DefaultOptions选项函数默认值作用WithChunkSize(n)512单个 chunk 的目标最大长度超出后触发二次切分WithChunkOverlap(n)100相邻 chunk 的重叠量用于保持上下文连续本例测试用 64WithSecondSplitter(s)递归字符分割器超长块的二次切分器默认分隔符\n\n、\n、WithCodeBlocks(bool)false是否保留围栏/缩进代码块false 时直接丢弃WithReferenceLinks(bool)false是否把[text][label]引用式链接用定义处的 URL 补全默认丢弃引用定义WithHeadingHierarchy(bool)false是否在每个 chunk 前缀完整标题层级true 时样例中会出现多级标题前缀WithJoinTableRows(bool)false表格是否按行独立成块false 时每行一个 chunk 并自动补表头WithLenFunc(fn)utf8.RuneCountInString计算字符串长度的函数决定长度口径字符数/字节数/token 数几个要点长度口径可换默认用 Unicode 字符数统计测试 TestMarkdownHeaderTextSplitter_LenFunc 展示了用tiktoken-go的cl100k_base编码按token 数计块的用法这对对齐 LLM 上下文窗口很有价值。表格行为splitTableRows 默认按行切分且每行 chunk 会自动补上表头与---分隔行开启WithJoinTableRows(true)后则把多行合并到接近 ChunkSize 为止。测试 TestMarkdownHeaderTextSplitter_Table 对两种行为均有断言。代码块WithCodeBlocks(true)时围栏代码块以\n\语言\n内容\n形式原样输出见onMDFence[markdown_splitter.go](https://link.gitcode.com/i/13d99729b9aae39602edc65eb2c39864)缩进代码块按 CommonMark Spec 4.4 每行补 4 空格onMDCodeBlock。关闭时两者被丢弃。内联元素splitInlinemarkdown_splitter.go在ReferenceLinksfalse时把软换行\n、硬换行\\\n、**/*/~~强调、行内代码、链接、图片等逐一还原保证 chunk 仍是合法 Markdown。五、如何复现与落地使用5.1 复现本样例在仓库根目录执行go test ./textsplitter/ -run TestMarkdownHeaderTextSplitter -v该测试会读取 example.md用WithChunkSize(512)、WithChunkOverlap(64)分割并重新写出 example_markdown_header_512.md你可以在本地看到完全一致的输出测试还同时覆盖了纯标题分割、表格、列表、代码块、内联元素、LenFunc 等 6 组用例。5.2 在自己的 RAG 流程中使用最小可用示例import ( github.com/tmc/langchaingo/schema github.com/tmc/langchaingo/textsplitter ) func main() { splitter : textsplitter.NewMarkdownTextSplitter( textsplitter.WithChunkSize(512), textsplitter.WithChunkOverlap(64), textsplitter.WithHeadingHierarchy(true), textsplitter.WithCodeBlocks(true), ) docs, err : textsplitter.CreateDocuments(splitter, []string{markdownSource}, nil) if err ! nil { panic(err) } for _, doc : range docs { _ schema.Document{PageContent: doc.PageContent, Metadata: doc.Metadata} } }【免费下载链接】langchaingoLangChain for Go, the easiest way to write LLM-based programs in Go项目地址: https://gitcode.com/GitHub_Trending/la/langchaingo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表