Skip to content

Commit

Permalink
upadte eino docs
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhahalong committed Jan 20, 2025
1 parent 7c96f4a commit 62432e4
Show file tree
Hide file tree
Showing 45 changed files with 430 additions and 311 deletions.
2 changes: 1 addition & 1 deletion content/zh/docs/eino/_index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
Description: Eino 是基于 Golang 的 AI 应用开发框架
date: "2025-01-15"
date: "2025-01-20"
lastmod: ""
linktitle: Eino
menu:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
Description: ""
date: "2025-01-15"
date: "2025-01-20"
lastmod: ""
tags: []
title: 'Eino: CallOption 能力与规范'
Expand All @@ -10,7 +10,7 @@ weight: 0
**CallOption**: 对 Graph 编译产物进行调用时,直接传递数据给特定的一组节点(Component、Implementation、Node)的渠道
- 和 节点 Config 的区别: 节点 Config 是实例粒度的配置,也就是从实例创建到实例消除,Config 中的值一旦确定就不需要改变了
- CallOption:是请求粒度的配置,不同的请求,其中的值是不一样的。更像是节点入参,但是这个入参是直接由 Graph 的入口直接传入,而不是上游节点传入。
- 举例:LarkDocLoader 中,需要提供请求粒度的 RefreshToken,这个 RefreshToken 每个用户每次使用后,都需要更换
- 举例:给一个 ChatModel 节点传入 Temperature 配置;给一个 Lambda 节点传入自定义 option。

## 组件 CallOption 形态

Expand All @@ -31,12 +31,12 @@ eino/components/model
// 抽象实现所在代码位置
eino-ext/components/model
├── maas
│   ├── call_option.go
│   └── Implementation.go
├── openai
├── claude
│   ├── option.go // Component 的一种实现的 CallOption 入参
│   └── chatmodel.go
├── ollama
│   ├── call_option.go // Component 的一种实现的 CallOption 入参
│   ├── Implementation.go
│   ├── chatmodel.go
```

### Model 抽象
Expand All @@ -60,11 +60,18 @@ type ChatModel interface {
}

// 此结构体是【组件抽象CallOption】的统一定义。 组件的实现可根据自己的需要取用【组件抽象CallOption】的信息
// Options is the common options for the model.
type Options struct {
Temperature float32
MaxTokens int
Model string
TopP float32
// Temperature is the temperature for the model, which controls the randomness of the model.
Temperature *float32
// MaxTokens is the max number of tokens, if reached the max tokens, the model will stop generating, and mostly return an finish reason of "length".
MaxTokens *int
// Model is the model name.
Model *string
// TopP is the top p for the model, which controls the diversity of the model.
TopP *float32
// Stop is the stop words for the model, which controls the stopping condition of the model.
Stop []string
}

// Option is the call option for ChatModel component.
Expand All @@ -78,34 +85,47 @@ type Option struct {
implSpecificOptFn any
}

// WithTemperature is the option to set the temperature for the model.
func WithTemperature(temperature float32) Option {
return Option{
apply: func(opts *Options) {
opts.Temperature = temperature
opts.Temperature = &temperature
},
}
}

// WithMaxTokens is the option to set the max tokens for the model.
func WithMaxTokens(maxTokens int) Option {
return Option{
apply: func(opts *Options) {
opts.MaxTokens = maxTokens
opts.MaxTokens = &maxTokens
},
}
}

// WithModel is the option to set the model name.
func WithModel(name string) Option {
return Option{
apply: func(opts *Options) {
opts.Model = name
opts.Model = &name
},
}
}

// WithTopP is the option to set the top p for the model.
func WithTopP(topP float32) Option {
return Option{
apply: func(opts *Options) {
opts.TopP = topP
opts.TopP = &topP
},
}
}

// WithStop is the option to set the stop words for the model.
func WithStop(stop []string) Option {
return Option{
apply: func(opts *Options) {
opts.Stop = stop
},
}
}
Expand Down Expand Up @@ -156,47 +176,29 @@ func GetImplSpecificOptions[T any](base *T, opts ...Option) *T {
}
```

### OpenAI 实现
### Claude 实现

> 组件的实现均类似 OpenAI 的实现
>
> 注:此处为样例,eino-ext/components/model 中暂时没有此场景
eino-ext/comodel/claude/option.go

```go
package openai
package claude

import (
"github.com/cloudwego/eino/components/model"
)

// openAIOptions 实现粒度的 CallOption 配置
type requestOptions struct {
APIKey string
Stop []string
PresencePenalty float32
}

// openai 下的 WithXX() 方法,只能对 openai 这一种实现生效
func WithAPIKey(apiKey string) model.Option {
return model.WrapImplSpecificOptFn[requestOptions](func(o *requestOptions) {
o.APIKey = apiKey
})
}

func WithStop(stop []string) model.Option {
return model.WrapImplSpecificOptFn[requestOptions](func(o *requestOptions) {
o.Stop = stop
})
type options struct {
TopK *int32
}

func WithPresencePenalty(presencePenalty float32) model.Option {
return model.WrapImplSpecificOptFn[requestOptions](func(o *requestOptions) {
o.PresencePenalty = presencePenalty
func WithTopK(k int32) model.Option {
return model.WrapImplSpecificOptFn(func(o *options) {
o.TopK = &k
})
}
```

model/openai/Implementation.go
model/claude/chatmodel.go

```go
type ChatModel struct {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
---
Description: ""
date: "2025-01-15"
date: "2025-01-20"
lastmod: ""
tags: []
title: 'Eino: Callback 用户手册'
weight: 0
---

> 💡
> TL;DR
>
> 长文,用意是“明确的、无歧义的、充分的”说明 Eino Callback 设计、实现和使用方式的各方面,可用作解决某个具体问题的工具参考,也可以作为入门后想要更进一步了解细节的一个途径。
>
> 快速入门请移步 :[Eino: 公共切面 - Callbacks](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callbacks_common_aspects)
## 解决的问题

Component(包括 Lambda)、Graph 编排共同解决“把业务逻辑定义出来”的问题。而 logging, tracing, metrics, 上屏展示等横切面性质的功能,需要有机制把功能注入到 Component(包括 Lambda)、Graph 中。
Expand All @@ -28,7 +21,7 @@ Callbacks 支持“**横切面功能注入**”和“**中间状态透出**”

### 触发实体

Component(包括官方定义的组件类型和 Lambda),Graph Node(以及 Chain Node),Graph 自身(以及 Chain)。这三类实体,都有横切面功能注入、中间状态透出的需求,因此都会触发 callback。具体见下面的“[触发方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual)触发方式”一节。
Component(包括官方定义的组件类型和 Lambda),Graph Node(以及 Chain Node),Graph 自身(以及 Chain)。这三类实体,都有横切面功能注入、中间状态透出的需求,因此都会触发 callback。具体见下面的“[触发方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual)”一节。

### 触发时机

Expand All @@ -45,7 +38,7 @@ const (
)
```

不同的触发实体,在不同场景下,是触发 OnStart 还是 OnStartWithStreamInput (OnEnd/OnEndWithStreamOutput 同理),具体的规则,详见下面的“[触发方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual)触发方式”一节。
不同的触发实体,在不同场景下,是触发 OnStart 还是 OnStartWithStreamInput (OnEnd/OnEndWithStreamOutput 同理),具体的规则,详见下面的“[触发方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual)”一节。

### Callback Handler

Expand All @@ -69,7 +62,7 @@ type Handler interface {

并都会返回新的 Context:用于**同一个 Handler 的不同触发时机之间**传递信息。

如果一个 Handler,不想关注所有的 5 个触发时机,只想关注一部分,比如只关注 OnStart,建议使用 `NewHandlerBuilder().OnStartFn(...).Build()`。如果不想关注所有的组件类型,只想关注特定组件,比如 ChatModel,建议使用 `NewHandlerHelper().ChatModel(...).Handler()`,可以只接收 ChatModel 的回调并拿到一个具体类型的 CallbackInput/CallbackOutput。具体见“[Handler 实现方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual) Handler 实现方式”一节。
如果一个 Handler,不想关注所有的 5 个触发时机,只想关注一部分,比如只关注 OnStart,建议使用 `NewHandlerBuilder().OnStartFn(...).Build()`。如果不想关注所有的组件类型,只想关注特定组件,比如 ChatModel,建议使用 `NewHandlerHelper().ChatModel(...).Handler()`,可以只接收 ChatModel 的回调并拿到一个具体类型的 CallbackInput/CallbackOutput。具体见“[Handler 实现方式](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual)”一节。

不同 Handler 之间,触发顺序**没有**保证。

Expand Down Expand Up @@ -121,8 +114,6 @@ type CallbackInput struct {
Messages []*schema.Message
// Tools is the tools to be used in the model.
Tools []*schema.ToolInfo
// ToolChoice is the tool choice, which controls the tool to be used in the model.
ToolChoice any // string / *schema.ToolInfo
// Config is the config for the model.
Config *Config
// Extra is the extra information for the callback.
Expand Down Expand Up @@ -194,6 +185,8 @@ Graph 会为内部所有的 Node 自动注入 RunInfo。机制是每个 Node 的

## 触发方式

![](/img/eino/graph_node_callback_run_place.png)

### 组件实现内部触发(Component Callback)

在组件实现的代码中,调用 callbacks 包中的 `OnStart(), OnEnd(), OnError(), OnStartWithStreamInput(), OnEndWithStreamInput()`。以 Ark 的 ChatModel 实现为例,在 Generate 方法中:
Expand Down Expand Up @@ -444,3 +437,15 @@ Handler 内不建议修改 input / output。原因是:
不同 Handler 之间,没有执行顺序的保证,因此不建议通过上面的机制在不同 Handler 间传递信息。本质上是无法保证某一个 Handler 返回的 context,一定会进入下一个 Handler 的函数执行中。

如果需要在不同 Handler 之间传递信息,建议的方式是在最外层的 context(如 graph 执行时传入的 context)中,设置一个全局的、请求维度的变量作为公共信息的存取空间,在各个 Handler 中按需读取和更新这个公共变量。在有 stream 的情况下,可能需要格外注意和保证这个公共变量的并发安全。

### 流切记要 Close

以存在 ChatModel 这种具有真流输出的节点为例,当存在 Callback 切面时,ChatModel 的输出流:
- 既要被下游节点作为输入来消费,又要被 Callback 切面来消费
- 一个流中的一个帧(Chunk),只能被一个消费方消费到,即流不是广播模型

所以此时需要将流进行复制,其复制关系如下:

![](/img/eino/graph_stream_chunk_copy.png)

- 如果其中一个 Callback n 没有 Close 对应的流,可能导致原始 Stream 无法 Close 和释放资源。
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
Description: ""
date: "2025-01-15"
date: "2025-01-20"
lastmod: ""
tags: []
title: 'Eino: 公共切面 - Callbacks'
Expand Down Expand Up @@ -308,7 +308,7 @@ var callbackHandler1 = &callbacks.HandlerBuilder{
}
```

1. 按照 [切面注入](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callbacks_common_aspects)切面注入 章节,选择合适的方式,将定制的消费切面注入到 Graph/Chain 即可
1. 按照 [切面注入](/zh/docs/eino/core_modules/chain_and_graph_orchestration/callbacks_common_aspects) 章节,选择合适的方式,将定制的消费切面注入到 Graph/Chain 即可

#### WARN:Callback 流切记要 Close

Expand Down Expand Up @@ -393,7 +393,7 @@ func (cm *ChatModel) Generate(ctx context.Context, in []*schema.Message, opts ..
}
```

注:当涉及到流式数据的切面上报时,需要将原来的流,Copy 出两份,一份作为输出,一份留作为 Callback 消费(CallbackManager 会根据 Callback Handler 的数量再次进行 Copy)。 针对流的相关操作,可参考 [Stream 流](/zh/docs/eino/overview) Stream 流 章节
注:当涉及到流式数据的切面上报时,需要将原来的流,Copy 出两份,一份作为输出,一份留作为 Callback 消费(CallbackManager 会根据 Callback Handler 的数量再次进行 Copy)。 针对流的相关操作,可参考 [Stream 流](/zh/docs/eino/overview) 章节

## 常见问题

Expand Down
Loading

0 comments on commit 62432e4

Please sign in to comment.