Eino中的组件-DocumentTransformer

Eino 的 DocumentTransformer 是一个文本预处理组件:把任意来源的原始文档拆成语义完整、长度合适的小片段,并附带丰富的元数据,为后续的 Embedding、Indexer、Retriever 乃至 ChatModel 提供“干净原料”。
典型动作:分割、过滤、合并、提取、结构化。

type Transformer interface {
    Transform(ctx context.Context,
              src []*schema.Document,
              opts ...TransformerOption) ([]*schema.Document, error)
}
  • 输入:[]*schema.Document(原始文档)
  • 输出:[]*schema.Document(转换后的片段)

每个 schema.Document 含

  • Content:正文
  • Metadata:来源、标题、页码、自定义 KV 等

官方已提供的实现(开箱即用)

实现 功能 场景
MarkdownHeaderSplitter 按 Markdown 标题层级切分 技术文档、README
TextSplitter(Recursive) 按字符/句子/段落递归切分,可指定 chunk-size & overlap 通用长文本
SemanticSplitter 先用 Embedding 得到语义边界,再切分 保证语义完整性
DocumentFilter 根据规则或正则过滤文档 剔除广告、敏感词
ScoreReranker 对片段重新打分排序 多路召回后精排

Document Loader与上下游组件的关系:

Document Loader(把文件/网页变成 Document) →

DocumentTransformer ( 把 Document 切成片段)→

Embedding(把片段向量化) → Indexer(把向量写入向量数据库) → Retriever(召回片段给 LLM 生成答案) → ChatTemplate → ChatModel

使用示例1:(独立使用)

ctx := context.Background()

    // 初始化 transformer (以 markdown 为例)
    transformer, err := markdown.NewHeaderSplitter(ctx, &markdown.HeaderConfig{
        // 配置参数
        Headers: map[string]string{
            "##": "headerNameOfLevel2",
        },
    })
    if err != nil {
        log.Fatalf("markdown.NewHeaderSplitter failed, err=%v", err)
    }

    markdownDoc := &schema.Document{
        Content: " #Title 0\n   测试内容 \n ## Title 1\nHello Word\n## Title 2\nWord Hello  \n ",
    }

    log.Printf("===== call Header Splitter directly =====")

    // 转换文档
    transformedDocs, err := transformer.Transform(ctx, []*schema.Document{markdownDoc})
    if err != nil {
        log.Fatalf("transformer.Transform failed, err=%v", err)
    }

    for idx, doc := range transformedDocs {
        log.Printf("doc segment %v: %v", idx, doc.Content)
    }

这里transformer按markdown的二级标题进行分割(注意1级及2级均会被分割), 测试输出如下图:

image.png

使用示例2:(在chain中使用)

 // 初始化 transformer (以 markdown 为例)
    transformer, err := markdown.NewHeaderSplitter(ctx, &markdown.HeaderConfig{
        // 配置参数
        Headers: map[string]string{
            "##": "headerNameOfLevel2",
        },
    })
    if err != nil {
        log.Fatalf("markdown.NewHeaderSplitter failed, err=%v", err)
    }

    markdownDoc := &schema.Document{
        Content: " #Title 0\n   测试内容 \n ## Title 1\nHello Word\n## Title 2\nWord Hello  \n ",
    }


chain := compose.NewChain[[]*schema.Document, []*schema.Document]()
    chain.AppendDocumentTransformer(transformer)

    // 在运行时使用
    run, err := chain.Compile(ctx)
    if err != nil {
        log.Fatalf("chain.Compile failed, err=%v", err)
    }

    outDocs, err := run.Invoke(ctx, []*schema.Document{markdownDoc})
    if err != nil {
        log.Fatalf("run.Invoke failed, err=%v", err)
    }

    for idx, doc := range outDocs {
        log.Printf("doc segment %v: %v", idx, doc.Content)
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容