document

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Nov 26, 2025 License: Apache-2.0 Imports: 13 Imported by: 0

README

Document Loaders and Splitters

完整的文档加载和分割系统,用于从各种来源加载文档并智能分割成可处理的块。

目录

概述

Document Loaders 和 Splitters 系统提供了强大的文档处理能力:

  • 多格式支持: 文本、Markdown、JSON、Web 页面
  • 智能分割: 字符、Token、递归、Markdown、代码等多种分割策略
  • 元数据保留: 自动保留和扩展文档元数据
  • Callback 集成: 完整的回调系统支持监控和调试
  • 高性能: 优化的分割算法,支持大规模文档处理

Document Loaders

支持的加载器
1. TextLoader

加载纯文本文件。

loader := document.NewTextLoader(document.TextLoaderConfig{
    FilePath: "document.txt",
    Encoding: "utf-8",
})

docs, err := loader.Load(context.Background())

特性:

  • 支持多种编码
  • 自动元数据提取(文件大小、路径等)
  • 高性能文件读取
2. MarkdownLoader

加载 Markdown 文件,支持结构解析。

loader := document.NewMarkdownLoader(document.MarkdownLoaderConfig{
    FilePath:      "README.md",
    RemoveImages:  true,
    RemoveLinks:   false,
    RemoveCodeFmt: false,
})

docs, err := loader.Load(context.Background())

特性:

  • 提取标题作为元数据
  • 可选移除图片、链接、代码格式
  • 保持 Markdown 结构
3. JSONLoader

加载 JSON 和 JSON Lines 格式。

loader := document.NewJSONLoader(document.JSONLoaderConfig{
    FilePath:     "data.json",
    JSONLines:    false,
    ContentKey:   "content",
    MetadataKeys: []string{"author", "date"},
})

docs, err := loader.Load(context.Background())

特性:

  • 支持标准 JSON 和 JSON Lines
  • 灵活的字段映射
  • 自动元数据提取
4. DirectoryLoader

批量加载目录中的文件。

loader := document.NewDirectoryLoader(document.DirectoryLoaderConfig{
    DirPath:   "./documents",
    Glob:      "*.txt",
    Recursive: true,
    Loader: func(path string) document.DocumentLoader {
        return document.NewTextLoader(document.TextLoaderConfig{
            FilePath: path,
        })
    },
})

docs, err := loader.Load(context.Background())

特性:

  • 支持 glob 模式匹配
  • 递归目录遍历
  • 自定义文件加载器
5. WebLoader

从 Web 加载内容。

loader := document.NewWebLoader(document.WebLoaderConfig{
    URL:       "https://example.com",
    StripHTML: true,
    Headers: map[string]string{
        "User-Agent": "MyBot/1.0",
    },
    Timeout: 30 * time.Second,
})

docs, err := loader.Load(context.Background())

特性:

  • HTTP/HTTPS 支持
  • 自定义请求头
  • HTML 标签移除
  • 超时控制

Text Splitters

支持的分割器
1. CharacterTextSplitter

基于字符数的简单分割。

splitter := document.NewCharacterTextSplitter(document.CharacterTextSplitterConfig{
    Separator:    "\n\n",
    ChunkSize:    1000,
    ChunkOverlap: 200,
})

chunks, err := splitter.SplitText(text)

特性:

  • 自定义分隔符
  • 块重叠支持
  • 简单高效
2. RecursiveCharacterTextSplitter

使用多层分隔符递归分割。

splitter := document.NewRecursiveCharacterTextSplitter(
    document.RecursiveCharacterTextSplitterConfig{
        Separators: []string{"\n\n", "\n", ". ", " "},
        ChunkSize:  1000,
        ChunkOverlap: 200,
    },
)

chunks, err := splitter.SplitText(text)

特性:

  • 智能选择分隔符
  • 保持语义完整性
  • 适用于自然语言
3. TokenTextSplitter

基于 Token 数量分割。

splitter := document.NewTokenTextSplitter(document.TokenTextSplitterConfig{
    Encoding:     "cl100k_base",
    ChunkSize:    500,
    ChunkOverlap: 50,
})

chunks, err := splitter.SplitText(text)

特性:

  • Token 级别精确控制
  • 适合 LLM 输入
  • 可配置编码方式
4. MarkdownTextSplitter

按 Markdown 结构分割。

splitter := document.NewMarkdownTextSplitter(document.MarkdownTextSplitterConfig{
    HeadersToSplitOn: []string{"#", "##", "###"},
    ChunkSize:        1000,
    ChunkOverlap:     100,
})

chunks, err := splitter.SplitText(markdown)

特性:

  • 保持 Markdown 结构
  • 按标题层级分割
  • 保留格式信息
5. CodeTextSplitter

针对代码的智能分割。

splitter := document.NewCodeTextSplitter(document.CodeTextSplitterConfig{
    Language:     document.LanguageGo,
    ChunkSize:    500,
    ChunkOverlap: 50,
})

chunks, err := splitter.SplitText(code)

支持的语言:

  • Go
  • Python
  • JavaScript/TypeScript
  • Java
  • Rust
  • C/C++

特性:

  • 保持代码结构
  • 函数/类级别分割
  • 语言特定分隔符

快速开始

基本用法
package main

import (
    "context"
    "fmt"

    "github.com/kart-io/goagent/document"
)

func main() {
    // 1. 加载文档
    loader := document.NewTextLoader(document.TextLoaderConfig{
        FilePath: "example.txt",
    })

    docs, err := loader.Load(context.Background())
    if err != nil {
        panic(err)
    }

    fmt.Printf("Loaded %d documents\n", len(docs))

    // 2. 分割文档
    splitter := document.NewRecursiveCharacterTextSplitter(
        document.RecursiveCharacterTextSplitterConfig{
            ChunkSize:    1000,
            ChunkOverlap: 200,
        },
    )

    chunks, err := splitter.SplitDocuments(docs)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Split into %d chunks\n", len(chunks))
}
Load and Split 组合
loader := document.NewMarkdownLoader(document.MarkdownLoaderConfig{
    FilePath: "README.md",
})

splitter := document.NewMarkdownTextSplitter(document.MarkdownTextSplitterConfig{
    ChunkSize: 500,
})

// 一步完成加载和分割
docs, err := loader.LoadAndSplit(context.Background(), splitter)
批量处理
loader := document.NewDirectoryLoader(document.DirectoryLoaderConfig{
    DirPath:   "./documents",
    Glob:      "*.md",
    Recursive: true,
})

splitter := document.NewRecursiveCharacterTextSplitter(
    document.RecursiveCharacterTextSplitterConfig{
        ChunkSize: 1000,
    },
)

docs, err := loader.LoadAndSplit(context.Background(), splitter)

API 参考

DocumentLoader 接口
type DocumentLoader interface {
    // 加载文档
    Load(ctx context.Context) ([]*retrieval.Document, error)

    // 加载并分割
    LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*retrieval.Document, error)

    // 获取元数据
    GetMetadata() map[string]interface{}
}
TextSplitter 接口
type TextSplitter interface {
    // 分割文本
    SplitText(text string) ([]string, error)

    // 分割文档
    SplitDocuments(docs []*retrieval.Document) ([]*retrieval.Document, error)

    // 获取配置
    GetChunkSize() int
    GetChunkOverlap() int
}
Document 结构
type Document struct {
    ID          string
    PageContent string
    Metadata    map[string]interface{}
    Score       float64
}

自动添加的元数据 (在分割时):

  • chunk_index: 块索引
  • chunk_total: 总块数
  • source_id: 源文档 ID

最佳实践

1. 选择合适的分割器
  • 自然语言: 使用 RecursiveCharacterTextSplitter
  • 代码: 使用 CodeTextSplitter 并指定语言
  • Markdown: 使用 MarkdownTextSplitter
  • 精确控制: 使用 TokenTextSplitter
2. 配置块大小
// 根据用途选择块大小
const (
    SmallChunk  = 500   // 精确搜索
    MediumChunk = 1000  // 通用用途
    LargeChunk  = 2000  // 长上下文
)
3. 使用重叠
// 重叠通常是块大小的 10-20%
splitter := document.NewCharacterTextSplitter(document.CharacterTextSplitterConfig{
    ChunkSize:    1000,
    ChunkOverlap: 200, // 20%
})
4. 批量处理
// 使用 DirectoryLoader 批量处理
loader := document.NewDirectoryLoader(document.DirectoryLoaderConfig{
    DirPath:   "./large-corpus",
    Recursive: true,
})

// 分批处理避免内存问题
docs, _ := loader.Load(ctx)
for i := 0; i < len(docs); i += batchSize {
    batch := docs[i:min(i+batchSize, len(docs))]
    // 处理批次
}
5. 元数据管理
// 添加自定义元数据
loader := document.NewTextLoader(document.TextLoaderConfig{
    FilePath: "doc.txt",
    Metadata: map[string]interface{}{
        "category":   "technical",
        "importance": "high",
        "version":    "1.0",
    },
})

性能优化

1. 内存优化
// 对于大文件,使用流式处理
// 或分批加载和处理

const batchSize = 100

for i := 0; i < totalDocs; i += batchSize {
    // 处理批次
    processBatch(i, min(i+batchSize, totalDocs))
}
2. 并发处理
// 并发处理多个文件
var wg sync.WaitGroup
semaphore := make(chan struct{}, 10) // 限制并发数

for _, file := range files {
    wg.Add(1)
    go func(f string) {
        defer wg.Done()
        semaphore <- struct{}{}
        defer func() { <-semaphore }()

        loader := document.NewTextLoader(document.TextLoaderConfig{
            FilePath: f,
        })
        docs, _ := loader.Load(ctx)
        // 处理文档
    }(file)
}

wg.Wait()
3. 缓存策略
// 缓存已加载的文档
type CachedLoader struct {
    loader document.DocumentLoader
    cache  map[string][]*retrieval.Document
    mu     sync.RWMutex
}

func (l *CachedLoader) Load(ctx context.Context) ([]*retrieval.Document, error) {
    key := l.getCacheKey()

    l.mu.RLock()
    if docs, ok := l.cache[key]; ok {
        l.mu.RUnlock()
        return docs, nil
    }
    l.mu.RUnlock()

    docs, err := l.loader.Load(ctx)
    if err != nil {
        return nil, err
    }

    l.mu.Lock()
    l.cache[key] = docs
    l.mu.Unlock()

    return docs, nil
}
4. 监控和调试
// 使用 Callbacks 监控性能
import "github.com/kart-io/goagent/core"

callbacks := core.NewCallbackManager(
    core.NewStdoutCallback(true), // 彩色输出
)

loader := document.NewTextLoader(document.TextLoaderConfig{
    FilePath:        "large-file.txt",
    CallbackManager: callbacks,
})

示例

完整示例请参考:

  • examples/loaders/ - 各种加载器示例
  • examples/splitters/ - 各种分割器示例
  • examples/advanced/ - 高级用法和场景

测试

运行测试:

go test -v ./document/...

运行基准测试:

go test -bench=. -benchmem ./document/...

相关文档

Documentation

Index

Constants

View Source
const (
	LanguageGo         = "go"
	LanguagePython     = "python"
	LanguageJavaScript = "javascript"
	LanguageTypeScript = "typescript"
	LanguageJava       = "java"
	LanguageRust       = "rust"
	LanguageCpp        = "cpp"
	LanguageC          = "c"
)

Language 支持的编程语言

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseDocumentLoader

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

BaseDocumentLoader 基础文档加载器

提供默认的 LoadAndSplit 实现

func NewBaseDocumentLoader

func NewBaseDocumentLoader(metadata map[string]interface{}, callbacks *core.CallbackManager) *BaseDocumentLoader

NewBaseDocumentLoader 创建基础加载器

func (*BaseDocumentLoader) GetCallbackManager

func (l *BaseDocumentLoader) GetCallbackManager() *core.CallbackManager

GetCallbackManager 获取回调管理器

func (*BaseDocumentLoader) GetMetadata

func (l *BaseDocumentLoader) GetMetadata() map[string]interface{}

GetMetadata 获取元数据

func (*BaseDocumentLoader) LoadAndSplit

func (l *BaseDocumentLoader) LoadAndSplit(
	ctx context.Context,
	loader DocumentLoader,
	splitter TextSplitter,
) ([]*interfaces.Document, error)

LoadAndSplit 默认实现:先加载后分割

type BaseTextSplitter

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

BaseTextSplitter 基础文本分割器

提供通用的分割逻辑

func NewBaseTextSplitter

func NewBaseTextSplitter(config BaseTextSplitterConfig) *BaseTextSplitter

NewBaseTextSplitter 创建基础分割器

func (*BaseTextSplitter) GetChunkOverlap

func (s *BaseTextSplitter) GetChunkOverlap() int

GetChunkOverlap 获取块重叠

func (*BaseTextSplitter) GetChunkSize

func (s *BaseTextSplitter) GetChunkSize() int

GetChunkSize 获取块大小

func (*BaseTextSplitter) MergeSplits

func (s *BaseTextSplitter) MergeSplits(splits []string, separator string) []string

MergeSplits 合并文本块

将多个文本块合并,保持在 chunk size 限制内

func (*BaseTextSplitter) SplitDocuments

func (s *BaseTextSplitter) SplitDocuments(docs []*interfaces.Document) ([]*interfaces.Document, error)

SplitDocuments 分割文档

func (*BaseTextSplitter) SplitText

func (s *BaseTextSplitter) SplitText(text string) ([]string, error)

SplitText 需要子类实现

func (*BaseTextSplitter) TriggerCallbacks

func (s *BaseTextSplitter) TriggerCallbacks(ctx context.Context, event string, data interface{}) error

TriggerCallbacks 触发回调

type BaseTextSplitterConfig

type BaseTextSplitterConfig struct {
	ChunkSize       int
	ChunkOverlap    int
	LengthFunction  func(string) int
	KeepSeparator   bool
	CallbackManager *core.CallbackManager
}

BaseTextSplitterConfig 基础分割器配置

type CharacterTextSplitter

type CharacterTextSplitter struct {
	*BaseTextSplitter
	// contains filtered or unexported fields
}

CharacterTextSplitter 字符分割器

按字符数分割文本,支持自定义分隔符

func NewCharacterTextSplitter

func NewCharacterTextSplitter(config CharacterTextSplitterConfig) *CharacterTextSplitter

NewCharacterTextSplitter 创建字符分割器

func (*CharacterTextSplitter) SplitText

func (s *CharacterTextSplitter) SplitText(text string) ([]string, error)

SplitText 分割文本

type CharacterTextSplitterConfig

type CharacterTextSplitterConfig struct {
	Separator       string
	ChunkSize       int
	ChunkOverlap    int
	KeepSeparator   bool
	CallbackManager *core.CallbackManager
}

CharacterTextSplitterConfig 字符分割器配置

type CodeTextSplitter

type CodeTextSplitter struct {
	*BaseTextSplitter
	// contains filtered or unexported fields
}

CodeTextSplitter 代码分割器

针对代码进行智能分割,保持代码结构完整性

func NewCodeTextSplitter

func NewCodeTextSplitter(config CodeTextSplitterConfig) *CodeTextSplitter

NewCodeTextSplitter 创建代码分割器

func (*CodeTextSplitter) SplitText

func (s *CodeTextSplitter) SplitText(text string) ([]string, error)

SplitText 分割代码

type CodeTextSplitterConfig

type CodeTextSplitterConfig struct {
	Language        string
	ChunkSize       int
	ChunkOverlap    int
	CallbackManager *core.CallbackManager
}

CodeTextSplitterConfig 代码分割器配置

type DirectoryLoader

type DirectoryLoader struct {
	*BaseDocumentLoader
	// contains filtered or unexported fields
}

DirectoryLoader 目录加载器

批量加载目录中的文件

func NewDirectoryLoader

func NewDirectoryLoader(config DirectoryLoaderConfig) *DirectoryLoader

NewDirectoryLoader 创建目录加载器

func (*DirectoryLoader) Load

Load 加载目录中的所有文件

func (*DirectoryLoader) LoadAndSplit

func (l *DirectoryLoader) LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

LoadAndSplit 加载并分割

type DirectoryLoaderConfig

type DirectoryLoaderConfig struct {
	DirPath         string
	Glob            string
	Recursive       bool
	Loader          func(string) DocumentLoader
	Metadata        map[string]interface{}
	CallbackManager *core.CallbackManager
}

DirectoryLoaderConfig 目录加载器配置

type DocumentLoader

type DocumentLoader interface {
	// Load 加载文档
	Load(ctx context.Context) ([]*interfaces.Document, error)

	// LoadAndSplit 加载并分割文档
	LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

	// GetMetadata 获取加载器元数据
	GetMetadata() map[string]interface{}
}

DocumentLoader 文档加载器接口

负责从各种来源加载文档,支持单独加载或加载后分割

type JSONLoader

type JSONLoader struct {
	*BaseDocumentLoader
	// contains filtered or unexported fields
}

JSONLoader JSON 文件加载器

加载 JSON 文件,支持 JSON Lines 格式

func NewJSONLoader

func NewJSONLoader(config JSONLoaderConfig) *JSONLoader

NewJSONLoader 创建 JSON 加载器

func (*JSONLoader) Load

func (l *JSONLoader) Load(ctx context.Context) ([]*interfaces.Document, error)

Load 加载 JSON 文件

func (*JSONLoader) LoadAndSplit

func (l *JSONLoader) LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

LoadAndSplit 加载并分割

type JSONLoaderConfig

type JSONLoaderConfig struct {
	FilePath        string
	JSONLines       bool     // 是否为 JSON Lines 格式
	ContentKey      string   // 内容字段的键
	MetadataKeys    []string // 要提取为元数据的键
	Metadata        map[string]interface{}
	CallbackManager *core.CallbackManager
}

JSONLoaderConfig JSON 加载器配置

type MarkdownLoader

type MarkdownLoader struct {
	*BaseDocumentLoader
	// contains filtered or unexported fields
}

MarkdownLoader Markdown 文件加载器

加载 Markdown 文件并提取结构信息

func NewMarkdownLoader

func NewMarkdownLoader(config MarkdownLoaderConfig) *MarkdownLoader

NewMarkdownLoader 创建 Markdown 加载器

func (*MarkdownLoader) Load

Load 加载 Markdown 文件

func (*MarkdownLoader) LoadAndSplit

func (l *MarkdownLoader) LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

LoadAndSplit 加载并分割

type MarkdownLoaderConfig

type MarkdownLoaderConfig struct {
	FilePath        string
	RemoveImages    bool
	RemoveLinks     bool
	RemoveCodeFmt   bool
	Metadata        map[string]interface{}
	CallbackManager *core.CallbackManager
}

MarkdownLoaderConfig Markdown 加载器配置

type MarkdownTextSplitter

type MarkdownTextSplitter struct {
	*BaseTextSplitter
	// contains filtered or unexported fields
}

MarkdownTextSplitter Markdown 智能分割器

按 Markdown 结构分割(标题、段落等)

func NewMarkdownTextSplitter

func NewMarkdownTextSplitter(config MarkdownTextSplitterConfig) *MarkdownTextSplitter

NewMarkdownTextSplitter 创建 Markdown 分割器

func (*MarkdownTextSplitter) SplitText

func (s *MarkdownTextSplitter) SplitText(text string) ([]string, error)

SplitText 按 Markdown 结构分割

type MarkdownTextSplitterConfig

type MarkdownTextSplitterConfig struct {
	HeadersToSplitOn []string // 要分割的标题级别,如 []string{"#", "##", "###"}
	ChunkSize        int
	ChunkOverlap     int
	CallbackManager  *core.CallbackManager
}

MarkdownTextSplitterConfig Markdown 分割器配置

type RecursiveCharacterTextSplitter

type RecursiveCharacterTextSplitter struct {
	*BaseTextSplitter
	// contains filtered or unexported fields
}

RecursiveCharacterTextSplitter 递归字符分割器

使用多个分隔符递归分割,优先使用段落、句子等自然边界

func NewRecursiveCharacterTextSplitter

func NewRecursiveCharacterTextSplitter(config RecursiveCharacterTextSplitterConfig) *RecursiveCharacterTextSplitter

NewRecursiveCharacterTextSplitter 创建递归分割器

func (*RecursiveCharacterTextSplitter) SplitText

func (s *RecursiveCharacterTextSplitter) SplitText(text string) ([]string, error)

SplitText 递归分割文本

type RecursiveCharacterTextSplitterConfig

type RecursiveCharacterTextSplitterConfig struct {
	Separators      []string
	ChunkSize       int
	ChunkOverlap    int
	KeepSeparator   bool
	CallbackManager *core.CallbackManager
}

RecursiveCharacterTextSplitterConfig 递归分割器配置

type TextLoader

type TextLoader struct {
	*BaseDocumentLoader
	// contains filtered or unexported fields
}

TextLoader 文本文件加载器

加载纯文本文件,支持各种编码

func NewTextLoader

func NewTextLoader(config TextLoaderConfig) *TextLoader

NewTextLoader 创建文本加载器

func (*TextLoader) Load

func (l *TextLoader) Load(ctx context.Context) ([]*interfaces.Document, error)

Load 加载文本文件

func (*TextLoader) LoadAndSplit

func (l *TextLoader) LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

LoadAndSplit 加载并分割

type TextLoaderConfig

type TextLoaderConfig struct {
	FilePath        string
	Encoding        string
	Metadata        map[string]interface{}
	CallbackManager *core.CallbackManager
}

TextLoaderConfig 文本加载器配置

type TextSplitter

type TextSplitter interface {
	// SplitText 分割文本
	SplitText(text string) ([]string, error)

	// SplitDocuments 分割文档
	SplitDocuments(docs []*interfaces.Document) ([]*interfaces.Document, error)

	// GetChunkSize 获取块大小
	GetChunkSize() int

	// GetChunkOverlap 获取块重叠大小
	GetChunkOverlap() int
}

TextSplitter 文本分割器接口

负责将长文本分割成更小的块,用于嵌入和检索

type TokenTextSplitter

type TokenTextSplitter struct {
	*BaseTextSplitter
	// contains filtered or unexported fields
}

TokenTextSplitter Token 分割器

按 token 数分割文本(简化实现,使用空格分词)

func NewTokenTextSplitter

func NewTokenTextSplitter(config TokenTextSplitterConfig) *TokenTextSplitter

NewTokenTextSplitter 创建 Token 分割器

func (*TokenTextSplitter) SplitText

func (s *TokenTextSplitter) SplitText(text string) ([]string, error)

SplitText 按 token 分割文本

type TokenTextSplitterConfig

type TokenTextSplitterConfig struct {
	Encoding        string // 编码方式(保留用于扩展)
	ChunkSize       int
	ChunkOverlap    int
	CallbackManager *core.CallbackManager
}

TokenTextSplitterConfig Token 分割器配置

type WebLoader

type WebLoader struct {
	*BaseDocumentLoader
	// contains filtered or unexported fields
}

WebLoader Web 页面加载器

通过 HTTP 加载 Web 页面内容

func NewWebLoader

func NewWebLoader(config WebLoaderConfig) *WebLoader

NewWebLoader 创建 Web 加载器

func (*WebLoader) Load

func (l *WebLoader) Load(ctx context.Context) ([]*interfaces.Document, error)

Load 加载 Web 页面

func (*WebLoader) LoadAndSplit

func (l *WebLoader) LoadAndSplit(ctx context.Context, splitter TextSplitter) ([]*interfaces.Document, error)

LoadAndSplit 加载并分割

type WebLoaderConfig

type WebLoaderConfig struct {
	URL             string
	Headers         map[string]string
	Timeout         time.Duration
	StripHTML       bool
	Metadata        map[string]interface{}
	CallbackManager *core.CallbackManager
}

WebLoaderConfig Web 加载器配置

Directories

Path Synopsis
examples
advanced command
loaders command
splitters command

Jump to

Keyboard shortcuts

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