部署DeepSeek模型,进群交流最in玩法!
立即加群
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >AI 写文章系列——Eino 介绍文档及 DeepSeek 示例

AI 写文章系列——Eino 介绍文档及 DeepSeek 示例

原创
作者头像
amc
修改2025-03-21 20:02:48
修改2025-03-21 20:02:48
1470
举报
文章被收录于专栏:后台全栈之路后台全栈之路

最近对 AI 的应用越来越多,甚至我学习的时候也会深度借助大模型,自己也写了一些 RAG 的代码辅助。我发现有些生成的文档还挺不错的,于是我就决定把这些还行的文档发出来,需要的朋友们也可以参考。

对于这些 AI 生成的文章,我会在标题和标签中说明,还请读者们明辨真假。


简介

Eino (谐音 "I know") 是用Go语言编写的一个强大的大型语言模型 (LLM) 应用开发框架。它借鉴了LangChain和LlamaIndex等优秀的LLM框架的思想,结合前沿研究成果与实际应用,提供了一个简洁、可扩展、可靠且有效的开发框架,更符合Go语言的编程惯例。

核心概念

1. 组件 (Components)

Eino框架中的组件是构建LLM应用的基本单元。每种组件都有特定的抽象接口定义以及多种可选的实现。

主要组件类型包括:

  • ChatModel:提供与大型语言模型交互的接口,支持生成式对话。
  • ChatTemplate:定义提示模板,用于构建发送给LLM的提示内容。
  • Embedding:将文本转换为向量表示。
  • Indexer:用于存储和索引文档向量。
  • Retriever:根据查询检索相关文档。
  • Loader:加载并解析各种格式的文档。
  • DocumentTransformer:处理和转换文档。
  • Tool:提供特定功能的工具,可被LLM调用。

每个组件都有两个核心接口:

  • Typer:获取组件实现的类型名称。
  • Checker:判断组件是否启用了回调功能。

2. 编排 (Orchestration)

Eino提供了两种编排API:Chain和Graph。

Chain:简单的链式有向图,只能向前推进。适合简单的数据流处理。

代码语言:go
复制
chain, _ := NewChain[map[string]any, *Message]().
           AppendChatTemplate(prompt).
           AppendChatModel(model).
           Compile(ctx)
chain.Invoke(ctx, map[string]any{"query": "what's your name?"})

Graph:可循环或非循环的有向图,功能强大且灵活。适合复杂的业务逻辑实现。

代码语言:go
复制
graph := NewGraph[map[string]any, *schema.Message]()
_ = graph.AddChatTemplateNode("node_template", chatTpl)
_ = graph.AddChatModelNode("node_model", chatModel)
_ = graph.AddToolsNode("node_tools", toolsNode)
_ = graph.AddLambdaNode("node_converter", takeOne)
_ = graph.AddEdge(START, "node_template")
...

3. 流式处理 (Stream Processing)

Eino提供了完整的流式处理能力,适用于处理实时生成的内容。框架支持以下流式处理范式:

流处理范式

解释

Invoke

接收非流类型 I,返回非流类型 O

Stream

接收非流类型 I,返回流类型 StreamReaderO

Collect

接收流类型 StreamReaderI,返回非流类型 O

Transform

接收流类型 StreamReaderI,返回流类型 StreamReaderO

当流处理需要时,Eino会自动进行:

  • 拼接 (Concatenate):将流式数据组合为非流式输入
  • 转换 (Convert):非流式数据转换为流式数据
  • 合并 (Merge):多个流合并为一个
  • 复制 (Copy):一个流复制到多个目的地

4. 切面 (Callbacks)

切面用于处理诸如日志记录、追踪、指标统计等横切面关注点。Eino支持五种切面:

  • OnStart:在组件执行前调用
  • OnEnd:在组件执行后调用
  • OnError:在组件执行出错时调用
  • OnStartWithStreamInput:在接收流输入时调用
  • OnEndWithStreamOutput:在输出流时调用

5. 状态 (State)

允许在Graph执行过程中维护和共享状态,实现更复杂的业务逻辑。

DeepSeek模型集成

Eino框架通过eino-ext提供了对DeepSeek模型的支持。DeepSeek是一个强大的语言模型,可以通过以下方式在Eino中使用:

代码语言:go
复制
// 创建DeepSeek模型
deepSeekModel, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
    Model:   "deepseek-reasoner", // 或其他DeepSeek模型
    APIKey:  os.Getenv("DEEPSEEK_API_KEY"),
    BaseURL: os.Getenv("DEEPSEEK_BASE_URL"), // 可选
})

// 生成回复
message, err := deepSeekModel.Generate(ctx, []*schema.Message{
    schema.SystemMessage("你是一个有帮助的助手。"),
    schema.UserMessage("什么是Eino框架?")
})

// 获取推理内容(仅适用于支持推理的模型,如deepseek-reasoner)
if reasoning, ok := deepseek.GetReasoningContent(message); ok {
    fmt.Println("推理过程:", reasoning)
}

DeepSeek模型配置支持多种参数,包括:

  • Model:要使用的模型ID(必填)
  • APIKey:认证密钥(必填)
  • BaseURL:自定义端点URL(可选,默认为https://api.deepseek.com/
  • Temperature:采样温度(可选,范围0.0, 2.0,默认1.0)
  • MaxTokens:生成的最大token数(可选,默认4096)
  • TopP:通过核采样控制多样性(可选,范围0.0, 1.0,默认1.0)
  • ResponseFormatType:响应格式类型(可选,"text"或"json_object")

基于DeepSeek的RAG工作流示例

下面是一个使用DeepSeek模型的RAG(检索增强生成)工作流示例:

代码语言:go
复制
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/cloudwego/eino/components/document"
    "github.com/cloudwego/eino/compose"
    "github.com/cloudwego/eino/schema"
    "github.com/cloudwego/eino-ext/components/document/loader/markdown"
    "github.com/cloudwego/eino-ext/components/document/transformer/splitter/recursive"
    "github.com/cloudwego/eino-ext/components/embedding/openai"
    "github.com/cloudwego/eino-ext/components/indexer/redis"
    "github.com/cloudwego/eino-ext/components/model/deepseek"
    "github.com/cloudwego/eino-ext/components/retriever/redis"
)

func main() {
    ctx := context.Background()
    
    // 1. 设置文档加载器
    loader, _ := markdown.NewLoader(ctx, &markdown.LoaderConfig{
        Source: document.Source{
            Path: "./知识库文档路径",
        },
    })
    
    // 2. 设置文档分割器
    splitter, _ := recursive.NewSplitter(ctx, &recursive.Config{
        ChunkSize:    1000,
        ChunkOverlap: 200,
    })
    
    // 3. 设置向量化模型
    embedder, _ := openai.NewEmbedding(ctx, &openai.EmbeddingConfig{
        APIKey: os.Getenv("OPENAI_API_KEY"),
        Model:  "text-embedding-3-large",
    })
    
    // 4. 设置索引器
    indexer, _ := redisindexer.NewIndexer(ctx, &redisindexer.IndexerConfig{
        Address:  "localhost:6379",
        Password: "",
        DBIndex:  0,
        IndexName: "eino-docs",
        Dimension: 3072, // 根据嵌入模型维度调整
    })
    
    // 5. 设置检索器
    retriever, _ := redisretriever.NewRetriever(ctx, &redisretriever.RetrieverConfig{
        Address:   "localhost:6379",
        Password:  "",
        DBIndex:   0,
        IndexName: "eino-docs",
        Embedding: embedder,
        TopK:      5,
    })
    
    // 6. 设置DeepSeek模型
    model, _ := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
        Model:   "deepseek-chat", // 或其他DeepSeek模型
        APIKey:  os.Getenv("DEEPSEEK_API_KEY"),
    })
    
    // 7. 定义RAG提示模板
    ragPrompt := `你是一个基于提供的上下文信息回答问题的助手。
    请仅使用提供的上下文来回答问题,如果上下文中不包含答案,请说"我不知道"。
    
    上下文:
    {{context}}
    
    问题: {{query}}
    
    回答:`
    
    // 8. 构建知识库索引流程
    indexingGraph := compose.NewGraph[document.Source, []string]()
    _ = indexingGraph.AddLoaderNode("loader", loader)
    _ = indexingGraph.AddDocumentTransformerNode("splitter", splitter)
    _ = indexingGraph.AddIndexerNode("indexer", indexer)
    _ = indexingGraph.AddEdge(compose.START, "loader")
    _ = indexingGraph.AddEdge("loader", "splitter")
    _ = indexingGraph.AddEdge("splitter", "indexer")
    _ = indexingGraph.AddEdge("indexer", compose.END)
    
    indexingRunnable, _ := indexingGraph.Compile(ctx, compose.WithGraphName("知识库索引流程"))
    
    // 执行索引流程
    _, err := indexingRunnable.Invoke(ctx, document.Source{
        Path: "./知识库文档路径",
    })
    if err != nil {
        fmt.Printf("索引失败: %v\n", err)
        return
    }
    
    // 9. 构建查询回答流程
    queryGraph := compose.NewGraph[string, *schema.Message]()
    
    // 添加检索节点
    _ = queryGraph.AddLambdaNode("retriever", func(ctx context.Context, query string) (map[string]any, error) {
        docs, err := retriever.Retrieve(ctx, query)
        if err != nil {
            return nil, err
        }
        
        // 合并文档内容作为上下文
        var context string
        for i, doc := range docs {
            context += fmt.Sprintf("%d. %s\n", i+1, doc.Content)
        }
        
        return map[string]any{
            "query":   query,
            "context": context,
        }, nil
    })
    
    // 添加提示模板节点
    template := schema.Jinja2.FromString(ragPrompt)
    _ = queryGraph.AddChatTemplateNode("prompt", template)
    
    // 添加模型节点
    _ = queryGraph.AddChatModelNode("model", model)
    
    // 连接边
    _ = queryGraph.AddEdge(compose.START, "retriever")
    _ = queryGraph.AddEdge("retriever", "prompt")
    _ = queryGraph.AddEdge("prompt", "model")
    _ = queryGraph.AddEdge("model", compose.END)
    
    queryRunnable, _ := queryGraph.Compile(ctx, compose.WithGraphName("RAG查询流程"))
    
    // 10. 执行查询
    userQuery := "Eino框架的主要组件有哪些?"
    response, err := queryRunnable.Invoke(ctx, userQuery)
    if err != nil {
        fmt.Printf("查询失败: %v\n", err)
        return
    }
    
    fmt.Printf("问题: %s\n回答: %s\n", userQuery, response.Content)
}

这个示例展示了一个完整的DeepSeek RAG工作流,包括以下步骤:

  1. 文档加载:使用Markdown加载器加载知识库文档
  2. 文档分割:使用递归分割器将文档分割成适当大小的片段
  3. 向量化:使用OpenAI的嵌入模型将文本转换为向量表示
  4. 索引:使用Redis作为向量数据库存储文档向量
  5. 检索:根据用户查询检索相关文档
  6. 提示构建:将检索到的文档与用户查询结合成提示
  7. 生成:使用DeepSeek模型基于提示生成回答

进阶功能

多查询检索

Eino提供了多查询检索(MultiQueryRetriever)功能,可以使用LLM生成多个不同的查询,从而提高检索的召回率:

代码语言:go
复制
multiRetriever, err := multiquery.NewRetriever(ctx, &multiquery.Config{
    // 使用DeepSeek模型生成多个查询
    RewriteLLM: deepSeekModel,
    // 原始检索器
    OrigRetriever: basicRetriever,
    // 最大查询数量
    MaxQueriesNum: 3,
})

// 使用多查询检索
docs, err := multiRetriever.Retrieve(ctx, "Eino框架如何构建RAG应用?")

ReAct智能体

Eino通过flow/agent/react包提供了开箱即用的ReAct智能体,可以自主思考、调用工具和生成答案:

代码语言:go
复制
// 创建工具
tools := []*schema.ToolInfo{
    {
        Name:        "search",
        Description: "搜索引擎,用于查找信息",
        Parameters:  schema.NewJSONSchemaProperties().AddString("query", "搜索查询", true),
    },
}

// 创建ReAct智能体
reactAgent, err := react.NewReActAgent(ctx, &react.ReActConfig{
    Model:     deepSeekModel,
    Tools:     tools,
    MaxTurns:  5,
    SystemPrompt: "你是一个有用的助手,能够思考并解决复杂问题。",
})

// 处理用户问题
response, err := reactAgent.Run(ctx, "北京明天的天气如何?")

框架结构

Eino框架由以下几个部分组成:

  • Eino:核心库,包含类型定义、流处理机制、组件抽象、编排功能和切面机制。
  • EinoExt:扩展库,提供各种组件实现、回调处理程序实现和工具。
  • Eino Devops:开发运维工具,包括可视化开发和调试工具。
  • EinoExamples:示例应用和最佳实践集合。

总结

Eino是一个强大的Go语言LLM应用开发框架,提供了丰富的组件、灵活的编排、完整的流式处理和切面注入能力。通过使用Eino,开发者可以快速构建复杂的LLM应用,如RAG系统、智能体、多模态应用等。

DeepSeek作为一个现代化的语言模型,与Eino的集成让开发者能够轻松地使用高质量的语言模型能力,构建智能应用。本文档展示了如何使用Eino和DeepSeek构建一个完整的RAG工作流,希望能够帮助开发者更好地理解和使用Eino框架。


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题:《AI 写文章系列——Eino 介绍文档及 DeepSeek 示例》

发布日期:2025-03-21

原文链接:https://cloud.tencent.com/developer/article/2506916

CC BY-NC-SA 4.0 DEED.png
CC BY-NC-SA 4.0 DEED.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 核心概念
    • 1. 组件 (Components)
    • 2. 编排 (Orchestration)
    • 3. 流式处理 (Stream Processing)
    • 4. 切面 (Callbacks)
    • 5. 状态 (State)
  • DeepSeek模型集成
  • 基于DeepSeek的RAG工作流示例
  • 进阶功能
    • 多查询检索
    • ReAct智能体
  • 框架结构
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档