Eino AI 实战: Eino 的文档加载与解析

基本介绍

Document Loader 是一个用于加载文档的组件。它的主要作用是从不同来源(如网络 URL、本地文件等)加载文档内容,并将其转换为标准的文档格式。这个组件在处理需要从各种来源获取文档内容的场景中发挥重要作用,比如:

  • 从网络 URL 加载网页内容
  • 读取本地 PDF、Word 等格式的文档

组件定义

2.1 接口定义

代码位置:eino/components/document/interface.go

go 复制代码
type Loader interface {
    Load(ctx context.Context, src Source, opts ...LoaderOption) ([]*schema.Document, error)
}

2.2 Load 方法

  • 功能:从指定的数据源加载文档

  • 参数:

    • ctx:上下文对象,用于传递请求级别的信息,同时也用于传递 Callback Manager
    • src:文档来源,包含文档的 URI 信息
    • opts:加载选项,用于配置加载行为
  • 返回值:

    • []*schema.Document:加载的文档列表
    • error:加载过程中的错误信息

2.3 Source 结构体

go 复制代码
type Source struct {
    URI string
}

Source 结构体定义了文档的来源信息:

  • URI:文档的统一资源标识符,可以是网络 URL 或本地文件路径

2.4 Document 结构体

go 复制代码
type Document struct {
    // ID 是文档的唯一标识符
    ID string
    // Content 是文档的内容
    Content string
    // MetaData 用于存储文档的元数据信息
    MetaData map[string]any
}

Document 结构体是文档的标准格式,包含以下重要字段:

  • ID:文档的唯一标识符,用于在系统中唯一标识一个文档

  • Content:文档的实际内容

  • MetaData:文档的元数据,可以存储如下信息:

    • 文档的来源信息
    • 文档的向量表示(用于向量检索)
    • 文档的分数(用于排序)
    • 文档的子索引(用于分层检索)
    • 其他自定义元数据

2.5 公共选项

  • Loader 组件使用 LoaderOption 来定义加载选项。
  • Loader 目前没有公共的 Option,每个具体的实现可以定义自己的特定选项,通过 WrapLoaderImplSpecificOptFn 函数包装成统一的 LoaderOption 类型。

应用

3.1 本地文件加载 (Loader - local file)

代码位置:eino-ext/components/document/loader/f ile/file_loader.go

配置参数说明:

  • UseNameAsID:是否将文件名用作文档 ID
  • Parser:文档解析器,如果不指定则使用默认的扩展名解析器(ExtParser,当前仅实现了 TextParser
go 复制代码
package main

import (
        "context"
        "github.com/cloudwego/eino-ext/components/document/loader/file"
        "github.com/cloudwego/eino/components/document"
        "github.com/cloudwego/eino/components/document/parser"
        "log"
)

func main() {
        ctx := context.Background()

        // 本地文件
        loader, _ := file.NewFileLoader(ctx, &file.FileLoaderConfig{
                UseNameAsID: true,
                Parser:      &parser.TextParser{}, // 可选:指定自定义解析器
        })
        filePath := "./file_data/Go 1.24震撼发布!这些新特性你必须知道!.md"
        docs, err := loader.Load(ctx, document.Source{
                URI: filePath,
        })
        if err != nil {
                panic(err)
        }

        log.Printf("doc content: %v", docs[0].Content)

        for _, doc := range docs {
                println(doc.Content) // go1.25 的新特性,不需要 fmt.Println
                println(doc.ID)
                // 访问元数据
                println(doc.MetaData[file.MetaKeyFileName])
                println(doc.MetaData[file.MetaKeyExtension])
                println(doc.MetaData[file.MetaKeySource])
        }
}

3.2 网络文件加载 (Loader - web url)

代码位置:eino-ext/components/document/loader/url/url.go

配置参数说明:

  • Parser:文档解析器,默认使用 HTML 解析器,会提取网页正文内容
  • Client:HTTP 客户端,可以自定义超时、代理等配置
  • RequestBuilder:请求构建器,用于自定义请求方法、请求头等
go 复制代码
package main

import (
    "context"
    "github.com/cloudwego/eino-ext/components/document/loader/url"
    "github.com/cloudwego/eino/components/document"
    "github.com/cloudwego/eino/components/document/parser"
    "log"
    "net/http"
)

func main() {
    ctx := context.Background()
  
    // 网络文件加载
    loader, _ := url.NewLoader(ctx, &url.LoaderConfig{
        Parser: &parser.TextParser{},
        Client: &http.Client{},
        RequestBuilder: func(ctx context.Context, source document.Source, opts ...document.LoaderOption) (*http.Request, error) {
          return nil, nil
        },
    })
  
    docs, err := loader.Load(ctx, document.Source{
        URI: "https://www.alipan.com/s/kKxyyXhjckz", // 真实的 pdf 文档的地址
    })
    if err != nil {
        panic(err)
    }

    log.Printf("doc content: %v", docs[0].Content)
    // 使用文档内容
    for _, doc := range docs {
        println(doc.Content)
    }
}

3.3 解析 PDF 为纯文本 (Parser - pdf)

代码位置:eino-ext/components/document/parser/pdf.pdf.go

配置参数说明:

  • ToPages:是否将 PDF 按页面分割成多个文档,默认为 false

解析选项:

  • 支持通过 parser.WithURI 设置文档 URI
  • 支持通过 parser.WithExtraMeta 添加额外元数据
go 复制代码
package main

import (
        "context"
        "log"
        "os"

        "github.com/cloudwego/eino-ext/components/document/parser/pdf"
)

func main() {
        ctx := context.Background()

        parser, _ := pdf.NewPDFParser(ctx, &pdf.Config{
                ToPages: false, // 是否按页面分割文档
        })

        file, err := os.Open("./file_data/2021-09《我们为什么控制不了自己》.pdf")
        if err != nil {
                log.Fatal(err)
        }

        defer file.Close()

        // 解析文档
        docs, err := parser.Parse(ctx, file)
        if err != nil {
                log.Fatal(err)
        }

        // 打印解析结果
        for _, doc := range docs {
                println(doc.Content)
        }
}

3.4 解析 HTML 为纯文本

代码位置:eino-ext/components/document/parser/html/html.go

配置参数说明:

  • Selector:可选参数,指定要提取的内容区域,使用 goquery 选择器语法

    • 例如:body 表示提取 标签内容
    • #content 表示提取 id 为 "content" 的元素内容

解析器会自动提取以下 metadata

  • html.MetaKeyTitle ("_title"):网页标题
  • html.MetaKeyDesc ("_description"):网页描述
  • html.MetaKeyLang ("_language"):网页语言
  • html.MetaKeyCharset ("_charset"):字符编码
  • html.MetaKeySource ("_source"):文档来源 URI
go 复制代码
package main

import (
        "context"
        "fmt"
        "strings"

        "github.com/cloudwego/eino-ext/components/document/parser/html"
)

func main() {
        ctx := context.Background()

        // 初始化解析器
        p, err := html.NewParser(ctx, &html.Config{
        Selector: "#content",   // 选择器,指定只提取 id 为 content 的元素内容,默认为 body
    }) // 使用默认配置
        if err != nil {
                panic(err)
        }

        // HTML 内容
        document := `
    <html lang="zh">
        <head>
            <title>示例页面</title>
            <meta name="description" content="这是一个示例页面">
            <meta charset="UTF-8">
        </head>
        <body>
            <div id="content">
                <h1>欢迎</h1>
                <p>这是正文内容。</p>
            </div>
        </body>
    </html>
    `

        // 解析文档
        docs, err := p.Parse(ctx, strings.NewReader(document))
        if err != nil {
                panic(err)
        }

        // 使用解析结果
        doc := docs[0]
        fmt.Println("内容:", doc.Content)
        fmt.Println("标题:", doc.MetaData[html.MetaKeyTitle])
        fmt.Println("描述:", doc.MetaData[html.MetaKeyDesc])
        fmt.Println("语言:", doc.MetaData[html.MetaKeyLang])
}

总结

Eino 框架是字节跳动内部半年多的使用和迭代,基于 Go 的大模型应用综合开发框架

介绍了 Eino: Components 组件中的 Document Loader 组件的用法

  • 本地文件加载
  • 远程文件加载
  • 解析 pdf
  • 解析 html

通过内部封装好的组件,可以更快、更高效的基实现大模型所具备的其中一个核心能力:

  • 基于语义的文本处理能力

这项能力可以让开发者专注与业务逻辑的实现,避免重复造轮子,以快速构建高质量的大模型应用。

相关推荐
码一行1 小时前
Eino AI 实战:DuckDuckGo 搜索工具 V1 与 V2
后端·go
未秃头的程序猿1 小时前
🚀 设计模式在复杂支付系统中的应用:策略+工厂+模板方法模式实战
后端·设计模式
踏浪无痕1 小时前
@Transactional的5种失效场景和自检清单
spring boot·后端·spring cloud
6***v4171 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
水痕011 小时前
go使用cobra来启动项目
开发语言·后端·golang
用户345848285051 小时前
python在使用synchronized关键字时,需要注意哪些细节问题?
后端
代码扳手1 小时前
Golang 高效内网文件传输实战:零拷贝、断点续传与 Protobuf 指令解析(含完整源码)
后端·go
银河邮差2 小时前
python实战-用海外代理IP抓LinkedIn热门岗位数据
后端·python
undsky2 小时前
【RuoYi-Eggjs】:让 MySQL 更简单
后端·node.js