Files
sundynix-agentix/sundynix-dispatcher/internal/dsl/compile.go
T
Blizzard aa574a8cb2 feat: DSL→对话编译 — Eino 图用节点字段而非整段 JSON 喂模型
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>
2026-06-10 16:34:38 +08:00

90 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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))
}