11---
22Description : " "
3- date : " 2025-01-15 "
3+ date : " 2025-01-20 "
44lastmod : " "
55tags : []
66title : ' Eino: CallOption 能力与规范'
@@ -10,7 +10,7 @@ weight: 0
1010** CallOption** : 对 Graph 编译产物进行调用时,直接传递数据给特定的一组节点(Component、Implementation、Node)的渠道
1111- 和 节点 Config 的区别: 节点 Config 是实例粒度的配置,也就是从实例创建到实例消除,Config 中的值一旦确定就不需要改变了
1212- CallOption:是请求粒度的配置,不同的请求,其中的值是不一样的。更像是节点入参,但是这个入参是直接由 Graph 的入口直接传入,而不是上游节点传入。
13- - 举例:LarkDocLoader 中,需要提供请求粒度的 RefreshToken,这个 RefreshToken 每个用户每次使用后,都需要更换
13+ - 举例:给一个 ChatModel 节点传入 Temperature 配置;给一个 Lambda 节点传入自定义 option。
1414
1515## 组件 CallOption 形态
1616
@@ -31,12 +31,12 @@ eino/components/model
3131
3232// 抽象实现所在代码位置
3333eino-ext/components/model
34- ├── maas
35- │ ├── call_option .go
36- │ └── Implementation .go
37- ├── openai
34+ ├── claude
35+ │ ├── option .go // Component 的一种实现的 CallOption 入参
36+ │ └── chatmodel .go
37+ ├── ollama
3838│ ├── call_option.go // Component 的一种实现的 CallOption 入参
39- │ ├── Implementation .go
39+ │ ├── chatmodel .go
4040```
4141
4242### Model 抽象
@@ -60,11 +60,18 @@ type ChatModel interface {
6060}
6161
6262// 此结构体是【组件抽象CallOption】的统一定义。 组件的实现可根据自己的需要取用【组件抽象CallOption】的信息
63+ // Options is the common options for the model.
6364type Options struct {
64- Temperature float32
65- MaxTokens int
66- Model string
67- TopP float32
65+ // Temperature is the temperature for the model, which controls the randomness of the model.
66+ Temperature *float32
67+ // 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".
68+ MaxTokens *int
69+ // Model is the model name.
70+ Model *string
71+ // TopP is the top p for the model, which controls the diversity of the model.
72+ TopP *float32
73+ // Stop is the stop words for the model, which controls the stopping condition of the model.
74+ Stop []string
6875}
6976
7077// Option is the call option for ChatModel component.
@@ -78,34 +85,47 @@ type Option struct {
7885 implSpecificOptFn any
7986}
8087
88+ // WithTemperature is the option to set the temperature for the model.
8189func WithTemperature (temperature float32 ) Option {
8290 return Option{
8391 apply: func (opts *Options) {
84- opts.Temperature = temperature
92+ opts.Temperature = & temperature
8593 },
8694 }
8795}
8896
97+ // WithMaxTokens is the option to set the max tokens for the model.
8998func WithMaxTokens (maxTokens int ) Option {
9099 return Option{
91100 apply: func (opts *Options) {
92- opts.MaxTokens = maxTokens
101+ opts.MaxTokens = & maxTokens
93102 },
94103 }
95104}
96105
106+ // WithModel is the option to set the model name.
97107func WithModel (name string ) Option {
98108 return Option{
99109 apply: func (opts *Options) {
100- opts.Model = name
110+ opts.Model = & name
101111 },
102112 }
103113}
104114
115+ // WithTopP is the option to set the top p for the model.
105116func WithTopP (topP float32 ) Option {
106117 return Option{
107118 apply: func (opts *Options) {
108- opts.TopP = topP
119+ opts.TopP = &topP
120+ },
121+ }
122+ }
123+
124+ // WithStop is the option to set the stop words for the model.
125+ func WithStop (stop []string ) Option {
126+ return Option{
127+ apply: func (opts *Options) {
128+ opts.Stop = stop
109129 },
110130 }
111131}
@@ -156,149 +176,116 @@ func GetImplSpecificOptions[T any](base *T, opts ...Option) *T {
156176}
157177```
158178
159- ### OpenAI 实现
179+ ### Claude 实现
160180
161- > 组件的实现均类似 OpenAI 的实现
162- >
163- > 注:此处为样例,eino-ext/components/model 中暂时没有此场景
181+ [ https://github.com/cloudwego/eino-ext/blob/main/components/model/claude/option.go ] ( https://github.com/cloudwego/eino-ext/blob/main/components/model/claude/option.go )
164182
165183``` go
166- package openai
184+ package claude
167185
168186import (
169187 " github.com/cloudwego/eino/components/model"
170188)
171189
172- // openAIOptions 实现粒度的 CallOption 配置
173- type requestOptions struct {
174- APIKey string
175- Stop []string
176- PresencePenalty float32
190+ type options struct {
191+ TopK *int32
177192}
178193
179- // openai 下的 WithXX() 方法,只能对 openai 这一种实现生效
180- func WithAPIKey (apiKey string ) model .Option {
181- return model.WrapImplSpecificOptFn [requestOptions](func (o *requestOptions) {
182- o.APIKey = apiKey
183- })
184- }
185-
186- func WithStop (stop []string ) model .Option {
187- return model.WrapImplSpecificOptFn [requestOptions](func (o *requestOptions) {
188- o.Stop = stop
189- })
190- }
191-
192- func WithPresencePenalty (presencePenalty float32 ) model .Option {
193- return model.WrapImplSpecificOptFn [requestOptions](func (o *requestOptions) {
194- o.PresencePenalty = presencePenalty
194+ func WithTopK (k int32 ) model .Option {
195+ return model.WrapImplSpecificOptFn (func (o *options) {
196+ o.TopK = &k
195197 })
196198}
197199```
198200
199- model/openai/Implementation .go
201+ [ https://github.com/cloudwego/eino-ext/blob/main/components/ model/claude/claude .go] ( https://github.com/cloudwego/eino-ext/blob/main/components/model/claude/claude.go )
200202
201203``` go
202- type ChatModel struct {}
204+ func (c *claude ) genMessageNewParams (input []*schema .Message , opts ...model .Option ) (anthropic .MessageNewParams , error ) {
205+ if len (input) == 0 {
206+ return anthropic.MessageNewParams {}, fmt.Errorf (" input is empty" )
207+ }
203208
204- func (cm *ChatModel ) Generate (ctx context .Context , in []*schema .Message , opts ...model .Option ) (
205-
206- cmOpts := model.GetCommonOptions(&model.Options{
207- Model: " gpt-3.5-turbo" ,
208- MaxTokens: 1024 ,
209- Temperature: 0.7 ,
210- }, opts...)
211-
212- implOpts := model.GetImplSpecificOptions [requestOptions](&requestOptions{
213- Stop : nil ,
214- PresencePenalty : 1 ,
209+ commonOptions := model.GetCommonOptions (&model.Options {
210+ Model: &c.model ,
211+ Temperature: c.temperature ,
212+ MaxTokens: &c.maxTokens ,
213+ TopP: c.topP ,
214+ Stop: c.stopSequences ,
215215 }, opts...)
216+ claudeOptions := model.GetImplSpecificOptions (&options{TopK: c.topK }, opts...)
216217
217- // 在这里开发 OpenAI 的 Model 逻辑
218- _ = cmOpts
219- _ = implOpts
218+ // omit mulple lines...
219+ return nil , nil
220220}
221+ ```
222+
223+ ## 编排中的 CallOption
221224
222- func (cm *ChatModel ) Stream (ctx context.Context, in []*schema.Message,
223- opts ...model.Option) (outStream *schema.StreamReader[*schema.Message], err error) {
224- // 同 Generate 接口
225+ [ https://github.com/cloudwego/eino/blob/main/compose/runnable.go ] ( https://github.com/cloudwego/eino/blob/main/compose/runnable.go )
226+
227+ Graph 编译产物是 Runnable
228+
229+ ``` go
230+ type Runnable [I, O any] interface {
231+ Invoke (ctx context.Context , input I , opts ...Option ) (output O, err error )
232+ Stream (ctx context.Context , input I , opts ...Option ) (output *schema.StreamReader [O], err error )
233+ Collect (ctx context.Context , input *schema.StreamReader [I], opts ...Option ) (output O, err error )
234+ Transform (ctx context.Context , input *schema.StreamReader [I], opts ...Option ) (output *schema.StreamReader [O], err error )
225235}
226236```
227237
228- ### Graph 编译产物
238+ Runnable 各方法均接收 compose.Option 列表。
229239
230- > Graph 的编译产物是 Runnable [ I, O ]
240+ [ https://github.com/cloudwego/eino/blob/main/compose/graph_call_options.go ] ( https://github.com/cloudwego/eino/blob/main/compose/graph_call_options.go )
231241
232- option.go
242+ 包括 graph run 整体的配置,各类组件的配置,特定 Lambda 的配置等。
233243
234244``` go
245+ // Option is a functional option type for calling a graph.
235246type Option struct {
236- options []any
237- nodeHandler []callbacks.Handler
238- keys []string
247+ options []any
248+ handler []callbacks.Handler
239249
240- graphHandler []callbacks.Handler
241- graphOption []GraphRunOption
242- }
250+ paths []*NodePath
243251
244- // 可指定 NodeKey 定点生效 CallOption
245- func (o Option ) DesignateNode (key ...string ) Option {
246- o.keys = append (o.keys , key...)
247- return o
252+ maxRunSteps int
248253}
249254
250- func WithChatModelOption (opts ...model .Option ) Option {
251- o := make ([]any, 0 , len (opts))
252- for i := range opts {
253- o = append (o, opts[i])
254- }
255- return Option{
256- options: o,
257- keys: make ([]string , 0 ),
255+ // DesignateNode set the key of the node which will the option be applied to.
256+ // notice: only effective at the top graph.
257+ // e.g.
258+ //
259+ // embeddingOption := compose.WithEmbeddingOption(embedding.WithModel("text-embedding-3-small"))
260+ // runnable.Invoke(ctx, "input", embeddingOption.DesignateNode("my_embedding_node"))
261+ func (o Option ) DesignateNode (key ...string ) Option {
262+ nKeys := make ([]*NodePath, len (key))
263+ for i , k := range key {
264+ nKeys[i] = NewNodePath (k)
258265 }
266+ return o.DesignateNodeWithPath (nKeys...)
259267}
260- ```
261-
262- runnable.go
263268
264- ``` go
265- type Runnable [I, O any] interface {
266- Invoke (ctx context.Context , input I , opts ...Option ) (output O, err error )
267- Stream (ctx context.Context , input I , opts ...Option ) (output *schema.StreamReader [O], err error )
268- Collect (ctx context.Context , input *schema.StreamReader [I], opts ...Option ) (output O, err error )
269- Transform (ctx context.Context , input *schema.StreamReader [I], opts ...Option ) (output *schema.StreamReader [O], err error )
269+ // DesignateNodeWithPath sets the path of the node(s) to which the option will be applied to.
270+ // You can make the option take effect in the subgraph by specifying the key of the subgraph.
271+ // e.g.
272+ // DesignateNodeWithPath({"sub graph node key", "node key within sub graph"})
273+ func (o Option ) DesignateNodeWithPath (path ...*NodePath ) Option {
274+ o.paths = append (o.paths , path...)
275+ return o
270276}
271- ```
272-
273- Graph 调用
274277
275- ``` go
276- g := NewGraph [map [string ]any, *schema.Message ]()
277-
278- _nodeOfModel := &openai.ChatModel {}_
279-
280- err = g.AddChatModelNode (" openAIModel" , _nodeOfModel_)
281-
282- r , err := g.Compile ()
283-
284- // 默认情况下,WithXXX() 的 Option 方法是按照 Component 的类型进行分发的
285- // 同一个 WithXXX() 会对同一种 Component 的不同实例同时生效
286- // 必要情况下可通过指定 NodeKey,仅针对一个 Node 生效 WithXXX() 方法
287- out, err = r.Invoke (ctx, in, WithChatModelOption (
288- openai.WithAKSK (" ak" , " sk" ),
289- openai.WithURL (" url" ),
290- ),
291- // 这组 CallOption 仅针对 openAIModel 这个节点生效
292- WithChatModelOption (
293- model.WithModel (" gpt-3.5-turto" ),
294- openai.WithAPIKey (" xxxx" ),
295- ).DesignateNode (" openAIModel" ),
296- )
278+ // WithEmbeddingOption is a functional option type for embedding component.
279+ // e.g.
280+ //
281+ // embeddingOption := compose.WithEmbeddingOption(embedding.WithModel("text-embedding-3-small"))
282+ // runnable.Invoke(ctx, "input", embeddingOption)
283+ func WithEmbeddingOption (opts ...embedding .Option ) Option {
284+ return withComponentOption (opts...)
285+ }
297286```
298287
299- ## 编排中的 CallOption
300-
301- CallOption 可以按需分配给 Graph 中不同的节点。
288+ compose.Option 可以按需分配给 Graph 中不同的节点。
302289
303290![ ] ( /img/eino/graph_runnable_after_compile.png )
304291
0 commit comments