aa574a8cb2
dispatcher 真正解析 DSL 图:input 节点文本=用户消息,agent 节点 system=系统提示词,
不再把整段 DSL JSON 当 prompt 丢给模型。
- dispatcher/internal/dsl: Compile(graph)→Plan{System,Query,Tools}
(input.text/agent.prompt→query, agent.system→system, tool.tool→tools, 兜底默认)
- eino/graph: recall 调 dsl.Compile,模板加 {system}(Agent 系统提示词+画像注入)
- eino/orchestrator: 写回历史落真实 query 而非 DSL 原文
- frontend nodeCatalog: input 节点改 text 字段(用户输入,必填),检查器可编辑
- 验证: 全模块+前端 build✓; 真实 DeepSeek——curl DSL(input '中国首都?')→'北京';
真实浏览器——加 input 节点输入'NATS是什么'→运行→DeepSeek 简洁正确作答
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
// Package dsl 把前端导出的 JSON DSL 图编译为可执行的对话计划。
|
||
// 当前从图中抽取「系统提示词 / 用户输入 / 工具节点」;后续可演进为
|
||
// compose.NewGraph 的完整多节点编译(分支/并行/工具节点逐一映射)。
|
||
package dsl
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// Node 是 DSL 图的一个节点(与前端 exportDsl 对齐)。
|
||
type Node struct {
|
||
ID string `json:"id"`
|
||
Kind string `json:"kind"`
|
||
Label string `json:"label"`
|
||
Config map[string]any `json:"config"`
|
||
}
|
||
|
||
// Edge 是一条连线。
|
||
type Edge struct {
|
||
Source string `json:"source"`
|
||
Target string `json:"target"`
|
||
}
|
||
|
||
// Flow 是整张图。
|
||
type Flow struct {
|
||
Version string `json:"version"`
|
||
Nodes []Node `json:"nodes"`
|
||
Edges []Edge `json:"edges"`
|
||
}
|
||
|
||
// Plan 是编译后的对话计划。
|
||
type Plan struct {
|
||
System string // 系统提示词(来自 agent 节点的 system;空则默认)
|
||
Query string // 用户输入(来自 input 节点 text / agent 节点 prompt)
|
||
Tools []string // 图中工具节点绑定的 MCP 工具名(供后续工具编排用)
|
||
}
|
||
|
||
const defaultSystem = "你是 sundynix-agentix 平台的 AI 助手。"
|
||
|
||
// Compile 解析 DSL 图,抽取对话计划。无法解析时退化为把原文当输入(兼容旧行为)。
|
||
func Compile(graph json.RawMessage) Plan {
|
||
var f Flow
|
||
if err := json.Unmarshal(graph, &f); err != nil || len(f.Nodes) == 0 {
|
||
return Plan{System: defaultSystem, Query: strings.TrimSpace(string(graph))}
|
||
}
|
||
|
||
var queries, systems, tools []string
|
||
for _, n := range f.Nodes {
|
||
switch n.Kind {
|
||
case "input":
|
||
if t := str(n.Config["text"]); t != "" {
|
||
queries = append(queries, t)
|
||
}
|
||
case "agent":
|
||
if s := str(n.Config["system"]); s != "" {
|
||
systems = append(systems, s)
|
||
}
|
||
if p := str(n.Config["prompt"]); p != "" { // 单 agent 节点快速测试时直接带 prompt
|
||
queries = append(queries, p)
|
||
}
|
||
case "tool":
|
||
if t := str(n.Config["tool"]); t != "" {
|
||
tools = append(tools, t)
|
||
}
|
||
}
|
||
}
|
||
|
||
system := strings.Join(systems, "\n")
|
||
if system == "" {
|
||
system = defaultSystem
|
||
}
|
||
query := strings.Join(queries, "\n")
|
||
if query == "" {
|
||
query = "你好" // 无结构化输入时的兜底,避免给模型发空消息
|
||
}
|
||
return Plan{System: system, Query: query, Tools: tools}
|
||
}
|
||
|
||
func str(v any) string {
|
||
if v == nil {
|
||
return ""
|
||
}
|
||
if s, ok := v.(string); ok {
|
||
return strings.TrimSpace(s)
|
||
}
|
||
return strings.TrimSpace(fmt.Sprint(v))
|
||
}
|