textsplitter

package
v0.14.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package textsplitter chunks markdown documents into metadata-bearing units suitable for embedding. It is vendored from github.com/tmc/langchaingo/textsplitter (MIT, see LICENSE-langchaingo) and adapted to the SDD chunker contract — see NOTICE.md for the full list of divergences from upstream.

Two splitters are exposed:

  • MarkdownTextSplitter: parses CommonMark, splits on h1–h6 headings, recursively re-splits oversized sections via a second splitter, and emits []Chunk with breadcrumb (heading-chain array), depth, and IsSummary / IsAttachment flags. The TextSplitter string interface is not satisfied; use SplitChunks for the chunk-bearing output.

  • RecursiveCharacter: splits on a separator hierarchy with overlap control. Used internally as the second splitter for oversized sections; satisfies the original TextSplitter string interface.

The high-level entry point is Splitter.Split, which strips YAML frontmatter, prepends an "Entry: <summary>" + "Breadcrumb: <chain>" preamble to each chunk's text per d-tac-jvd, and tags chunks with attachment provenance.

Index

Constants

View Source
const (
	DefaultChunkSize    = 3200
	DefaultChunkOverlap = 320
)

Default rune-count chunk size and overlap for markdown body splitting. Calibrated to roughly the d-tac-lqr "~800 tokens hard cap, ~10% overlap" targets (1 token ≈ 4 runes English prose).

Variables

This section is empty.

Functions

This section is empty.

Types

type Chunk

type Chunk struct {
	Text                 string
	Breadcrumb           []string
	Depth                int
	IsSummary            bool
	IsAttachment         bool
	SourceAttachmentPath string
	// Body is the section text without the Entry/Breadcrumb preamble. Useful
	// for citation snippets (the user-facing surface) where the preamble
	// would be noise.
	Body string
}

Chunk is one unit of text destined for embedding, carrying the metadata needed to filter, score, and cite it. The Text field already includes the `Entry: <summary>\nBreadcrumb: <chain>\n\n<body>` preamble (per d-tac-jvd) — embedders consume Text directly.

Breadcrumb is the heading-chain in array form (e.g. ["Approach", "Storage"]) without `#` markers. Depth is the deepest heading level the chunk sits under (0 means pre-heading body).

IsSummary, IsAttachment, and SourceAttachmentPath are provenance flags the indexer uses for filtering and citation rendering.

type MarkdownTextSplitter

type MarkdownTextSplitter struct {
	ChunkSize      int
	ChunkOverlap   int
	SecondSplitter TextSplitter
	CodeBlocks     bool
	ReferenceLinks bool
	JoinTableRows  bool
	LenFunc        func(string) int
}

MarkdownTextSplitter parses CommonMark markdown via the gitlab.com/golang-commonmark/markdown tokenizer and splits the input on h1–h6 heading boundaries, recursively re-splitting oversized sections via SecondSplitter. Output chunks carry breadcrumb metadata (the heading-chain as []string) and depth (the deepest heading level encountered). The caller is responsible for composing any Entry/Breadcrumb preamble — see splitter.go.

func NewMarkdownTextSplitter

func NewMarkdownTextSplitter(opts ...Option) *MarkdownTextSplitter

NewMarkdownTextSplitter creates a new Markdown text splitter.

func (MarkdownTextSplitter) SplitChunks

func (sp MarkdownTextSplitter) SplitChunks(text string) ([]rawChunk, error)

SplitChunks tokenizes the input markdown and emits rawChunks split on h1–h6 heading boundaries.

type Option

type Option func(*Options)

Option is a function that can be used to set options for a text splitter.

func WithChunkOverlap

func WithChunkOverlap(chunkOverlap int) Option

WithChunkOverlap sets the chunk overlap for a text splitter.

func WithChunkSize

func WithChunkSize(chunkSize int) Option

WithChunkSize sets the chunk size for a text splitter.

func WithCodeBlocks

func WithCodeBlocks(renderCode bool) Option

WithCodeBlocks sets whether indented and fenced codeblocks should be included in the output. SDD default is true.

func WithHeadingHierarchy

func WithHeadingHierarchy(trackHeadingHierarchy bool) Option

WithHeadingHierarchy is retained for upstream API parity but unused by the SDD entry point: breadcrumb prepending is handled by the high-level splitter rather than by the markdown splitter inlining heading-stack text into chunks.

func WithJoinTableRows

func WithJoinTableRows(join bool) Option

WithJoinTableRows sets whether tables should be split by row or not.

func WithKeepSeparator

func WithKeepSeparator(keepSeparator bool) Option

WithKeepSeparator sets whether the separators should be kept in the resulting split text or not.

func WithLenFunc

func WithLenFunc(lenFunc func(string) int) Option

WithLenFunc sets the lenfunc for a text splitter.

func WithReferenceLinks(referenceLinks bool) Option

WithReferenceLinks sets whether reference links (i.e. `[text][label]`) should be patched with the url and title from their definition.

func WithSecondSplitter

func WithSecondSplitter(secondSplitter TextSplitter) Option

WithSecondSplitter sets the second splitter for a text splitter.

func WithSeparators

func WithSeparators(separators []string) Option

WithSeparators sets the separators for a text splitter.

type Options

type Options struct {
	ChunkSize            int
	ChunkOverlap         int
	Separators           []string
	KeepSeparator        bool
	LenFunc              func(string) int
	SecondSplitter       TextSplitter
	CodeBlocks           bool
	ReferenceLinks       bool
	KeepHeadingHierarchy bool // retained for upstream API parity; unused by the SDD entry point
	JoinTableRows        bool
}

Options is a struct that contains options for a text splitter.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns the default options for all text splitters.

type RecursiveCharacter

type RecursiveCharacter struct {
	Separators    []string
	ChunkSize     int
	ChunkOverlap  int
	LenFunc       func(string) int
	KeepSeparator bool
}

RecursiveCharacter is a text splitter that will split texts recursively by different characters.

func NewRecursiveCharacter

func NewRecursiveCharacter(opts ...Option) RecursiveCharacter

NewRecursiveCharacter creates a new recursive character splitter with default values. By default the separators are "\n\n", "\n", " " and "".

func (RecursiveCharacter) SplitText

func (s RecursiveCharacter) SplitText(text string) ([]string, error)

SplitText splits a text into multiple text fragments.

type SplitInput

type SplitInput struct {
	// Markdown is the document text. May start with a YAML frontmatter block
	// delimited by `---` lines; if so it is stripped before tokenization
	// and surfaced as Frontmatter on the result.
	Markdown string
	// EntrySummary is prepended to each chunk's Text as `Entry: <first
	// sentence>` so embeddings carry entry-level identity (per d-tac-jvd).
	// Only the first sentence is used; pass the entry's stored summary
	// verbatim and the splitter handles trimming.
	EntrySummary string
	// IsAttachment marks this input as an attachment. Each chunk's
	// IsAttachment flag is set accordingly and SourceAttachmentPath is
	// recorded on each chunk.
	IsAttachment bool
	// SourceAttachmentPath is the relative path of the source attachment
	// (e.g. `2026/05/04-235258-d-tac-lqr/design.md`). Recorded on each
	// chunk when IsAttachment is true.
	SourceAttachmentPath string
}

SplitInput captures everything the splitter needs to produce per-chunk output for a single source document.

type SplitOutput

type SplitOutput struct {
	Chunks      []Chunk
	Frontmatter map[string]any
}

SplitOutput carries the per-input results: chunks ready to embed plus the stripped frontmatter as a generic map for the caller's filterable metadata layer (frontmatter values are not embedded as text per d-tac-lqr).

type Splitter

type Splitter struct {
	// contains filtered or unexported fields
}

Splitter is the high-level entry point for chunking SDD entry bodies and attachments. It strips YAML frontmatter at the package boundary, runs the markdown splitter, and composes the `Entry: <summary>\nBreadcrumb: <chain>` preamble onto each chunk's Text. Construct via NewSplitter.

func NewSplitter

func NewSplitter(opts ...Option) *Splitter

NewSplitter constructs a Splitter with the given markdown splitter options. Defaults match DefaultOptions() (CodeBlocks=true, ChunkSize=DefaultChunkSize, ChunkOverlap=DefaultChunkOverlap).

func (*Splitter) Split

func (s *Splitter) Split(input SplitInput) (SplitOutput, error)

Split chunks input.Markdown. Heading-only sections produce no chunk; entries without `##` headings produce a single body chunk after summary is added separately by the caller. Frontmatter is parsed from the document head (delimited by `---` lines) and returned via SplitOutput.Frontmatter.

func (*Splitter) SummaryChunk

func (s *Splitter) SummaryChunk(summary string) (Chunk, bool)

SummaryChunk produces the dedicated entry-summary chunk. The text is the raw summary (no preamble — the summary already self-identifies). IsSummary is set so the indexer can apply the depth-aware boost at retrieval time. Returns the zero-value Chunk and false when summary is empty so callers can skip indexing entries without summaries.

type TextSplitter

type TextSplitter interface {
	SplitText(text string) ([]string, error)
}

TextSplitter is the standard interface for splitting texts into string fragments. The MarkdownTextSplitter does not satisfy this interface — see SplitChunks for the chunk-bearing output. RecursiveCharacter still implements TextSplitter and is used internally as the secondary splitter for oversized markdown sections.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL