feat: compose.NewGraph 全图编译 — 工具节点在 Eino 图里真实执行
dispatcher 按每个任务的 DSL 动态编译 Eino 图:工具/检索节点按拓扑序作为真实图 节点经 NATS 调 MCP,产出注入模型上下文。不再是固定的 recall→prompt→model。 - dsl: 加 Parse(图结构) + (Flow)Topo(Kahn 拓扑序,环退化声明序) + ToolBinding(tool/ retriever 节点→工具名+参数) - eino/compile.go: 逐任务 compileFlow —— START→init(身份+记忆召回)→tool_n(真调 MCP, 失败降级)→prompt(黑板 RunCtx 组装 system+画像+工具产出+历史+输入)→model→END - eino/orchestrator: 去掉启动期静态图,Handle 内按 DSL 动态编译;删旧 graph.go/state.go - 工具节点产出作为参考资料注入 system,模型据此作答 - 验证: 全模块 build✓ + e2e PASS; 真实 DeepSeek 双证——回归(input+agent)→'蓝色'; 工具节点(echo 注入事实)→mcp-go 日志证明图里真调 echo→模型据参考资料答'…Milvus…' 注: 分支/并行节点(compose.Branch/fan-out)暂未编译,是更大 TODO。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudwego/eino/compose"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
|
||||
"github.com/sundynix/sundynix-dispatcher/internal/dsl"
|
||||
@@ -33,34 +32,36 @@ type ToolCaller interface {
|
||||
// 工具调用超时;超时即降级(不带工具上下文继续推理)。
|
||||
const toolCallTimeout = 3 * time.Second
|
||||
|
||||
// Orchestrator 把 DSL 任务交给编译好的 Eino 图执行(记忆召回 → 注入 → 流式)。
|
||||
// Orchestrator 把每个 DSL 任务动态编译为 Eino 图并执行(记忆召回 → 工具节点 → 注入 → 流式)。
|
||||
type Orchestrator struct {
|
||||
pool *llm.Pool
|
||||
breaker *harness.CircuitBreaker
|
||||
sink TokenSink
|
||||
tools ToolCaller
|
||||
run compose.Runnable[*contract.Task, *schema.Message]
|
||||
}
|
||||
|
||||
// NewOrchestrator 构建并编译记忆增强图。
|
||||
// NewOrchestrator 持有依赖;图按任务的 DSL 在 Handle 内动态编译。
|
||||
func NewOrchestrator(pool *llm.Pool, breaker *harness.CircuitBreaker, sink TokenSink, tools ToolCaller) (*Orchestrator, error) {
|
||||
o := &Orchestrator{breaker: breaker, sink: sink, tools: tools}
|
||||
run, err := buildGraph(context.Background(), pool, o.fetchMemory, o.fetchHistory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o.run = run
|
||||
return o, nil
|
||||
return &Orchestrator{pool: pool, breaker: breaker, sink: sink, tools: tools}, nil
|
||||
}
|
||||
|
||||
// Handle 消费一个任务:执行 Eino 图,把 Token 流回流到 sundynix.streams.<id>。
|
||||
// Handle 消费一个任务:按 DSL 编译 Eino 图并执行,把 Token 流回流到 sundynix.streams.<id>。
|
||||
func (o *Orchestrator) Handle(ctx context.Context, t *contract.Task) error {
|
||||
if !o.breaker.Allow() {
|
||||
log.Printf("[eino] circuit open, drop task %s", t.ID)
|
||||
return nil
|
||||
}
|
||||
log.Printf("[eino] task %s received (graph=%d bytes), running graph...", t.ID, len(t.Graph))
|
||||
log.Printf("[eino] task %s received (graph=%d bytes), compiling DSL → Eino graph...", t.ID, len(t.Graph))
|
||||
|
||||
stream, err := o.run.Stream(ctx, t)
|
||||
run, err := o.compileFlow(ctx, t)
|
||||
if err != nil {
|
||||
log.Printf("[eino] task %s compile error: %v", t.ID, err)
|
||||
_ = o.sink.CompleteStream(t.ID)
|
||||
o.breaker.Report(false)
|
||||
return err
|
||||
}
|
||||
|
||||
stream, err := run.Stream(ctx, t)
|
||||
if err != nil {
|
||||
log.Printf("[eino] task %s graph error: %v", t.ID, err)
|
||||
_ = o.sink.CompleteStream(t.ID)
|
||||
|
||||
Reference in New Issue
Block a user