Skip to content

Commit dbe848a

Browse files
authored
docs: eino image resize (#1219)
1 parent 805b4b6 commit dbe848a

File tree

11 files changed

+194
-165
lines changed

11 files changed

+194
-165
lines changed

content/zh/docs/eino/core_modules/chain_and_graph_orchestration/call_option_capabilities.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func WithEmbeddingOption(opts ...embedding.Option) Option {
287287

288288
compose.Option 可以按需分配给 Graph 中不同的节点。
289289

290-
![](/img/eino/graph_runnable_after_compile.png)
290+
<a href="/img/eino/graph_runnable_after_compile.png" target="_blank"><img src="/img/eino/graph_runnable_after_compile.png" /></a>
291291

292292
```go
293293
// 所有节点都生效的 call option

content/zh/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ Graph 会为内部所有的 Node 自动注入 RunInfo。机制是每个 Node 的
185185

186186
## 触发方式
187187

188-
![](/img/eino/graph_node_callback_run_place.png)
188+
<a href="/img/eino/graph_node_callback_run_place.png" target="_blank"><img src="/img/eino/graph_node_callback_run_place.png" /></a>
189189

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

@@ -446,6 +446,6 @@ Handler 内不建议修改 input / output。原因是:
446446

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

449-
![](/img/eino/graph_stream_chunk_copy.png)
449+
<a href="/img/eino/graph_stream_chunk_copy.png" target="_blank"><img src="/img/eino/graph_stream_chunk_copy.png" /></a>
450450

451451
- 如果其中一个 Callback n 没有 Close 对应的流,可能导致原始 Stream 无法 Close 和释放资源。

content/zh/docs/eino/core_modules/chain_and_graph_orchestration/orchestration_design_principles.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
Description: ""
3-
date: "2025-01-20"
3+
date: "2025-01-23"
44
lastmod: ""
55
tags: []
66
title: 'Eino: 编排的设计理念'
@@ -28,7 +28,7 @@ eino 的最基础编排方式为 graph,以及简化的封装 chain。不论是
2828

2929
就如下图:
3030

31-
![](/img/eino/edge_type_validate.png)
31+
<a href="/img/eino/edge_type_validate.png" target="_blank"><img src="/img/eino/edge_type_validate.png" /></a>
3232

3333
对于一个编排而言,只有下游能识别和处理上游的输出,这个编排才能正常运行。 这个基本假设在 eino 中被清晰地表达了出来,让开发者在用 eino 做编排时,能够有十足的信心清楚编排的逻辑是如何运行和流转的,而不是从一系列的 any 中去猜测传过来的值是否正确。
3434

@@ -42,7 +42,7 @@ eino 的最基础编排方式为 graph,以及简化的封装 chain。不论是
4242

4343
> 这是一个模拟 ① 直接和大模型对话 ② 使用 RAG 模式 的场景,最后结果可用于对比两种模式的效果
4444
45-
![](/img/eino/input_output_type_validate.png)
45+
<a href="/img/eino/input_output_type_validate.png" target="_blank"><img src="/img/eino/input_output_type_validate.png" /></a>
4646

4747
图中绿色的部分,就是普通的 Edge 连接,其要求上游的输出必须能 `assign` 给下游,可以接收的类型有:
4848

@@ -64,6 +64,8 @@ eino 的最基础编排方式为 graph,以及简化的封装 chain。不论是
6464

6565
> 这是一个模拟 react agent 的运行逻辑
6666
67+
<a href="/img/eino/branch_to_draw_loop.png" target="_blank"><img src="/img/eino/branch_to_draw_loop.png" /></a>
68+
6769
可以看到,一个 branch 本身拥有一个 `condition`, 这个 function 的输入必须和上游类型对齐。同时,一个 branch 后所接的各个节点,也必须和 condition 一样,要能接收上游的输出。
6870

6971
### chain 中的类型对齐
@@ -72,7 +74,7 @@ eino 的最基础编排方式为 graph,以及简化的封装 chain。不论是
7274

7375
从抽象角度看,chain 就是一个 `链条`,如下所示:
7476

75-
![](/img/eino/what_is_chain.png)
77+
<a href="/img/eino/what_is_chain.png" target="_blank"><img src="/img/eino/what_is_chain.png" /></a>
7678

7779
逻辑节点的类型可以分为 3 类:
7880

@@ -106,15 +108,15 @@ func TestChain() {
106108

107109
上面的逻辑用图来表示如下:
108110

109-
![](/img/eino/nodes_type_validate.png)
111+
<a href="/img/eino/nodes_type_validate.png" target="_blank"><img src="/img/eino/nodes_type_validate.png" /></a>
110112

111113
若上下游的类型没有对齐,chain 会在 chain.Compile() 时返回错误。而 graph 会在 graph.AddXXXNode() 时就报错。
112114

113115
#### parallel
114116

115117
parallel 在 chain 中是一类特殊的节点,从 chain 的角度看 parallel 和其他的节点没啥区别。在 parallel 内部,其基本拓扑结构如下:
116118

117-
![](/img/eino/same_type_of_parallel.png)
119+
<a href="/img/eino/same_type_of_parallel.png" target="_blank"><img src="/img/eino/same_type_of_parallel.png" /></a>
118120

119121
graph 中的多 edge 形成的结构其中一种就是这个,这里的基本假设是: 一个 parallel 的每一条边上有且仅有一个节点。当然,这一个节点也可以是 graph。但注意,目前框架没有直接提供在 parallel 中嵌套 branch 或 parallel 的能力。
120122

@@ -150,7 +152,7 @@ func TestParallel() {
150152

151153
> 图中是模拟同一个提问,由不同的大模型去回答,结果可用于对比效果
152154
153-
![](/img/eino/graph_as_chain_node.png)
155+
<a href="/img/eino/graph_as_chain_node.png" target="_blank"><img src="/img/eino/graph_as_chain_node.png" /></a>
154156

155157
> 需要注意的是,这个结构只是逻辑上的视角,由于 chain 本身也是用 graph 实现的,parallel 在底层 graph 中会平铺到图中。
156158
@@ -172,7 +174,7 @@ Workflow 的类型对齐的维度,由整体的 Input & Output 改成了字段
172174

173175
在 Eino 中,编排的结果是 graph 或 chain,若要运行,则需要使用 `Compile()` 来生成一个 `Runnable` 接口。
174176

175-
Runnable 的一个重要作用就是提供了 `I``nvoke``S``tream``C``ollect``T``ransform` 四种调用方式。
177+
Runnable 的一个重要作用就是提供了 「Invoke」、「Stream」、「Collect」、「Transform」 四种调用方式。
176178

177179
> 上述几种调用方式的介绍以及详细的 Runnable 介绍可以查看: [Eino: 基础概念介绍](/zh/docs/eino/overview)
178180
@@ -235,7 +237,7 @@ func TestTypeMatch(t *testing.T) {
235237

236238
当我们以 Stream 方式调用上面编译好的 Runnable 时,model 节点会输出 `*schema.StreamReader[*Message]`,但是 lambda 节点是 InvokableLambda,只接收非流式的 `*schema.Message` 作为输入。这也符合类型对齐规则,因为 Eino 框架会自动把流式的 Message 拼接成完整的 Message。
237239

238-
在 stream 模式下,`拼接``帧` 是一个非常常见的操作,拼接时,会先把 `*StreamReader[T] ` 中的所有元素取出来转成 `[]T`,再尝试把 `[]T` 拼接成一个完整的 `T`。框架内已经内置支持了如下类型的拼接:
240+
在 stream 模式下,拼接帧 是一个非常常见的操作,拼接时,会先把 `*StreamReader[T] ` 中的所有元素取出来转成 `[]T`,再尝试把 `[]T` 拼接成一个完整的 `T`。框架内已经内置支持了如下类型的拼接:
239241

240242
- `*schema.Message`: 详情见 `schema.ConcatMessages()`
241243
- `string`: 实现逻辑等同于 `+=`
@@ -278,7 +280,7 @@ eino 的 Graph 类型对齐检查,会在 `err = graph.AddEdge("node1", "node2"
278280

279281
其结构可见下图:
280282

281-
![](/img/eino/input_type_output_type_in_edge.png)
283+
<a href="/img/eino/input_type_output_type_in_edge.png" target="_blank"><img src="/img/eino/input_type_output_type_in_edge.png" /></a>
282284

283285
这种场景适用于开发者能自行处理好上下游类型对齐的情况,可根据不同类型选择下游执行节点。
284286

@@ -362,7 +364,7 @@ Eino 支持各种维度的 Call Option 分配方式:
362364

363365
以一个添加了 StatePreHandler、StatePostHandler、InputKey、OutputKey,且内部没有实现 Callback 切面的 InvokableLambda(输入为 string,输出为 int)为例,在图中的流式执行完整时序如下:
364366

365-
![](/img/eino/graph_node_run_wrapper.png)
367+
<a href="/img/eino/graph_node_run_wrapper.png" target="_blank"><img src="/img/eino/graph_node_run_wrapper.png" /></a>
366368

367369
在 workflow 的场景中,字段映射发生在两个位置:
368370

@@ -376,11 +378,11 @@ Eino 支持各种维度的 Call Option 分配方式:
376378
- 当前执行中的一个或多个节点,所有的后序节点,作为一个 SuperStep,整体一起执行。这时,这些新的节点,会成为“当前”节点。
377379
- 支持 Branch,支持图中有环,但是可能需要人为添加 passthrough 节点,来确保 SuperStep 中的节点符合预期,如下图:
378380

379-
![](/img/eino/graph_steps_in_graph2.png)
381+
<a href="/img/eino/graph_steps_in_graph2.png" target="_blank"><img src="/img/eino/graph_steps_in_graph2.png" /></a>
380382

381383
上图中 Node 4 和 Node 5 按规则被放在一起执行,大概率不符合预期。需要改成:
382384

383-
![](/img/eino/graph_steps_in_graph.png)
385+
<a href="/img/eino/graph_steps_in_graph.png" target="_blank"><img src="/img/eino/graph_steps_in_graph.png" /></a>
384386

385387
`NodeTriggerMode == AllPredecessor` 时,图以 dag 引擎执行,对应的拓扑结构是有向无环图。特点是:
386388

content/zh/docs/eino/core_modules/chain_and_graph_orchestration/stream_programming_essentials.md

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
Description: ""
3-
date: "2025-01-20"
3+
date: "2025-01-23"
44
lastmod: ""
55
tags: []
66
title: Eino 流式编程要点
@@ -12,7 +12,7 @@ weight: 0
1212
1313
## 编排流式概述
1414

15-
![](/img/eino/eino_component_runnable.png)
15+
<a href="/img/eino/eino_component_runnable.png" target="_blank"><img src="/img/eino/eino_component_runnable.png" /></a>
1616

1717
编排流式的 Graph 时,需要考虑的几个关键要素:
1818

@@ -41,9 +41,9 @@ Eino 是个 "component first" 的框架,组件可以独立使用。定组件
4141

4242
```go
4343
type ChatModel interface {
44-
Generate(ctx context.Context**, **input []*schema.Message**, **opts ...Option) (*schema.Message**, **error)
45-
Stream(ctx context.Context**, **input []*schema.Message**, **opts ...Option) (
46-
*schema.StreamReader[*schema.Message]**, **error)
44+
Generate(ctx context.Context, input []*schema.Message, opts ...Option) (*schema.Message, error)
45+
Stream(ctx context.Context, input []*schema.Message, opts ...Option) (
46+
*schema.StreamReader[*schema.Message], error)
4747
// other methods omitted...
4848
}
4949
```
@@ -52,7 +52,7 @@ type ChatModel interface {
5252

5353
```go
5454
type Retriever interface {
55-
Retrieve(ctx context.Context**, **query string**, **opts ...Option) ([]*schema.Document**, **error)
55+
Retrieve(ctx context.Context, query string, opts ...Option) ([]*schema.Document, error)
5656
}
5757
```
5858

@@ -93,11 +93,11 @@ Collect 和 Transform 两种流式范式,目前只在编排场景有用到。
9393

9494
但是,一个组件,一旦处在多个组件组合使用的“编排”场景中,它的入参和出参就没那么固定了,而是取决于这个组件在编排场景中的“上游输出”和“下游输入”。比如 React Agent 的典型编排示意图:
9595

96-
![](/img/eino/chatmodel_to_tool.png)
96+
<a href="/img/eino/chatmodel_to_tool.png" target="_blank"><img src="/img/eino/chatmodel_to_tool.png" /></a>
9797

9898
上图中,如果 Tool 是个 StreamableTool,也就是输出是 StreamReader[Message],则 Tool -> ChatModel 就可能是流式的输出。但是 Chat Model 并没有接收流式输入的业务场景,也没有对应的接口。这时 Eino 框架会自动帮助 ChatModel 补足接收流式输入的能力:
9999

100-
![](/img/eino/chatmodel_tool_loop.png)
100+
<a href="/img/eino/chatmodel_tool_loop.png" target="_blank"><img src="/img/eino/chatmodel_tool_loop.png" /></a>
101101

102102
上面的 Concat message stream 是 Eino 框架自动提供的能力,即使不是 message,是任意的 T,只要满足特定的条件,Eino 框架都会自动去做这个 StreamReader[T] 到 T 的转化,这个条件是:**在编排中,当一个组件的上游输出是 StreamReader[T],但是组件只提供了 T 作为输入的业务接口时,框架会自动将 StreamReader[T] concat 成 T,再输入给这个组件。**
103103

@@ -106,23 +106,23 @@ Collect 和 Transform 两种流式范式,目前只在编排场景有用到。
106106
107107
另一方面,考虑一个相反的例子。还是 React Agent,这次是一个更完整的编排示意图:
108108

109-
![](/img/eino/tool_model_react.png)
109+
<a href="/img/eino/tool_model_react.png" target="_blank"><img src="/img/eino/tool_model_react.png" /></a>
110110

111111
在上图中,branch 接收 chat model 输出的 message,并根据 message 中是否包含 tool call,来选择直接结束 agent 本次运行并将 message 输出,还是调用 Tool 并将调用结果再次给 Chat Model 循环处理。由于这个 Branch 可以通过 message stream 的首个帧就完成逻辑判断,因此我们给这个 Branch 定义的是 Collect 接口,即流式输入,非流式输出:
112112

113113
```go
114-
compose.NewStreamGraphBranch(func(ctx context.Context**, **sr *schema.StreamReader[*schema.Message]) (endNode string**, **err error) {
115-
msg**, **err := sr.Recv()
114+
compose.NewStreamGraphBranch(func(ctx context.Context, sr *schema.StreamReader[*schema.Message]) (endNode string, err error) {
115+
msg, err := sr.Recv()
116116
if err != nil {
117-
return ""**, **err
117+
return "", err
118118
}
119119
defer sr.Close()
120120

121-
if len(msg.ToolCalls) == **0 **{
122-
return compose._END_**, **nil
121+
if len(msg.ToolCalls) == 0 {
122+
return compose._END_, nil
123123
}
124124

125-
return nodeKeyTools**, **nil
125+
return nodeKeyTools, nil
126126
}
127127
```
128128

@@ -165,11 +165,11 @@ ReactAgent 有两个接口,Generate 和 Stream,分别实现了 Invoke 和 St
165165
- “没有”:整体而言,Graph,Chain 等编排产物,自身是没有业务属性的,只为抽象的编排服务的,因此也就没有符合业务场景的接口范式。同时,编排需要支持各种范式的业务场景。所以,Eino 中代表编排产物的 Runnable[I, O] 接口,不做选择也无法选择,提供了所有流式范式的方法:
166166

167167
```go
168-
type Runnable[I**, **O any] interface {
169-
Invoke(ctx context.Context**, **input I**, **opts ...Option) (output O**, **err error)
170-
Stream(ctx context.Context**, **input I**, **opts ...Option) (output *schema.StreamReader[O]**, **err error)
171-
Collect(ctx context.Context**, **input *schema.StreamReader[I]**, **opts ...Option) (output O**, **err error)
172-
Transform(ctx context.Context**, **input *schema.StreamReader[I]**, **opts ...Option) (output *schema.StreamReader[O]**, **err error)
168+
type Runnable[I, O any] interface {
169+
Invoke(ctx context.Context, input I, opts ...Option) (output O, err error)
170+
Stream(ctx context.Context, input I, opts ...Option) (output *schema.StreamReader[O], err error)
171+
Collect(ctx context.Context, input *schema.StreamReader[I], opts ...Option) (output O, err error)
172+
Transform(ctx context.Context, input *schema.StreamReader[I], opts ...Option) (output *schema.StreamReader[O], err error)
173173
}
174174
```
175175

@@ -179,27 +179,33 @@ type Runnable[I**, **O any] interface {
179179

180180
从另一个角度看,既然编排产物整体可以被看做“组件”,那“组件”必然有自己的内部实现,比如 ChatModel 的内部实现逻辑,可能是把入参的 []Message 转化成各个模型的 API request,之后调用模型的 API,获取 response 后再转化成出参的 Message。那么类比的话,Graph 这个“组件”的内部实现是什么?是数据在 Graph 内部各个组件间以用户指定的流转方向和流式范式来流转。其中,“流转方向”不在当前讨论范围内,而各组件运行时的流式范式,则由 Graph 整体的触发方式决定,具体来说:
181181

182-
- 如果用户通过 Invoke 来调用 Graph,则 Graph 内部所有组件都以 Invoke 范式来调用。如果某个组件,没有实现 Invoke 范式,则 Eino 框架自动根据组件实现了的流式范式,封装出 Invoke 调用范式,优先顺位如下:
183-
- 若组件实现了 Stream,则通过 Stream 封装 Invoke,即自动 concat 输出流。
182+
如果用户通过 **Invoke** 来调用 Graph,则 Graph 内部所有组件都以 Invoke 范式来调用。如果某个组件,没有实现 Invoke 范式,则 Eino 框架自动根据组件实现了的流式范式,封装出 Invoke 调用范式,优先顺位如下:
183+
184+
- 若组件实现了 Stream,则通过 Stream 封装 Invoke,即自动 concat 输出流。
185+
186+
<a href="/img/eino/invoke_outside_stream_inside.png" target="_blank"><img src="/img/eino/invoke_outside_stream_inside.png" /></a>
184187

185-
![](/img/eino/invoke_outside_stream_inside.png)
186188
- 否则,若组件实现了 Collect,则通过 Collect 封装 Invoke,即非流式入参转单帧流。
187189

188-
![](/img/eino/invoke_outside_collect_inside.png)
190+
<a href="/img/eino/invoke_outside_collect_inside.png" target="_blank"><img src="/img/eino/invoke_outside_collect_inside.png" /></a>
191+
189192
- 如果都没实现,则必须实现 Transform,通过 Transform 封装 Invoke,即入参转单帧流,出参 concat。
190193

191-
![](/img/eino/invoke_outside_transform_inside.png)
194+
<a href="/img/eino/invoke_outside_transform_inside.png" target="_blank"><img src="/img/eino/invoke_outside_transform_inside.png" /></a>
192195

193-
- 如果用户通过 Stream/Collect/Transform 来调用 Graph,则 Graph 内部所有组件都以 Transform 范式来调用。如果某个组件,没有实现 Transform 范式,则 Eino 框架自动根据组件实现了的流式范式,封装出 Transform 调用范式,优先顺位如下:
194-
- 若组件实现了 Stream,则通过 Stream 封装 Transform,即自动 concat 输入流。
196+
如果用户通过 **Stream/Collect/Transform** 来调用 Graph,则 Graph 内部所有组件都以 Transform 范式来调用。如果某个组件,没有实现 Transform 范式,则 Eino 框架自动根据组件实现了的流式范式,封装出 Transform 调用范式,优先顺位如下:
197+
198+
- 若组件实现了 Stream,则通过 Stream 封装 Transform,即自动 concat 输入流。
199+
200+
<a href="/img/eino/transform_inside_stream_inside.png" target="_blank"><img src="/img/eino/transform_inside_stream_inside.png" /></a>
195201

196-
![](/img/eino/transform_inside_stream_inside.png)
197202
- 否则,若组件实现了 Collect,则通过 Collect 封装 Transform,即非流式出参转单帧流。
198203

199-
![](/img/eino/transform_outside_stream_inside.png)
204+
<a href="/img/eino/transform_outside_stream_inside.png" target="_blank"><img src="/img/eino/transform_outside_stream_inside.png" /></a>
205+
200206
- 如果都没实现,则必须实现 Invoke,通过 Invoke 封装 Transform,即入参流 concat,出参转单帧流
201207

202-
![](/img/eino/transform_outside_invoke_inside.png)
208+
<a href="/img/eino/transform_outside_invoke_inside.png" target="_blank"><img src="/img/eino/transform_outside_invoke_inside.png" /></a>
203209

204210
结合上面穷举的各种案例,Eino 框架对 T 和 Stream[T] 的自动转换,可以总结为:
205211

content/zh/docs/eino/core_modules/devops/ide_plugin_guide.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,50 +15,52 @@ weight: 1
1515
1616
## 简介
1717

18-
![](/img/eino/eino_dev_ability_introduction_page.png)
18+
<a href="/img/eino/eino_dev_ability_introduction_page.png" target="_blank"><img src="/img/eino/eino_dev_ability_introduction_page.png" /></a>
1919

2020
## 安装插件
2121

2222
<table><tbody><tr>
2323
<td>
2424
1. 进入<strong>GoLand</strong>,点击<strong>设置,选择Plugin 插件</strong>
25-
<img src="/img/eino/eino_install_page.png" />
25+
<a href="/img/eino/eino_install_page.png" target="_blank"><img src="/img/eino/eino_install_page.png" /></a>
2626

2727
</td>
2828
<td>
2929
1. <strong>通过Marketplace,搜索Eino Dev 插件并按照</strong>
30-
<img src="/img/eino/eino_install_page_2_page.png" />
30+
<a href="/img/eino/eino_install_page_2_page.png" target="_blank"><img src="/img/eino/eino_install_page_2_page.png" /></a>
3131

3232
</td>
3333
</tr></tbody></table>
3434

3535
> 💡
3636
> **插件安装完毕可以在 IDE 右侧插件列表中 EinoDev 调试插件图标啦,接下来就可以体验插件提供的调试与编排能力啦**
3737
38-
![](/img/eino/eino_dev_enter_page.png)
38+
<a href="/img/eino/eino_dev_enter_page.png" target="_blank"><img src="/img/eino/eino_dev_enter_page.png" /></a>
3939

4040
## 功能简介
4141

4242
### **EinoDev Graph 编排**
4343

4444
<table><tbody><tr>
4545
<td>
46-
<img src="/img/eino/eino_orchestration_index_page.png" />
46+
<a href="/img/eino/eino_orchestration_index_page.png" target="_blank"><img src="/img/eino/eino_orchestration_index_page.png" /></a>
47+
4748
</td>
4849
<td>
49-
<img src="/img/eino/eino_orchestration_show_nodes_2_page.png" />
50+
<a href="/img/eino/eino_orchestration_show_nodes_2_page.png" target="_blank"><img src="/img/eino/eino_orchestration_show_nodes_2_page.png" /></a>
51+
5052
</td>
5153
</tr></tbody></table>
5254

5355
### **EinoDev Graph 调试**
5456

5557
<table><tbody><tr>
5658
<td>
57-
<img src="/img/eino/eino_debug_run_page.png" />
59+
<a href="/img/eino/eino_debug_run_page.png" target="_blank"><img src="/img/eino/eino_debug_run_page.png" /></a>
60+
5861
</td>
5962
<td>
60-
<img src="/img/eino/eino_debug_test_run_of_mock_data_page.png" />
63+
<a href="/img/eino/eino_debug_test_run_of_mock_data_page.png" target="_blank"><img src="/img/eino/eino_debug_test_run_of_mock_data_page.png" /></a>
64+
6165
</td>
6266
</tr></tbody></table>
63-
64-
##

0 commit comments

Comments
 (0)