Version: 0.9.18.dev.260415
后端: 1. ChatNode 路由从 GenerateJSON 重构为流式控制码路由 - 新建 backend/newAgent/router/chat_route.go:流式增量控制码解析器 StreamRouteParser,复用 agent 的 <SMARTFLOW_ROUTE> 正则模式 - 更新 backend/newAgent/node/chat.go:RunChatNode 从 GenerateJSON(阻塞等完整 JSON)改为 Stream + 控制码解析 + 分支流式处理 - streamAndDispatch 核心循环:逐 chunk 喂解析器,控制码解析后按 route 分发 - handleDirectReplyStream:thinking=false 同一流续传,thinking=true 关流后二次 thinking 调用 - handleDeepAnswerStream:移除"让我想想"过渡语,直接关流后发起第二次流式调用(thinking 由 effectiveThinking 控制) - handleRouteExecuteStream / handleRoutePlanStream:关流 → 推送 status → 设 Phase - 更新 backend/newAgent/prompt/chat.go:路由 prompt 从 JSON 格式改为控制码标签格式 - 更新 backend/newAgent/model/chat_contract.go:ChatRoutingDecision 新增 Thinking / Raw 字段,移除 Speak / Reason 2. Thinking 参数从 bool 扩展为 string 三态 - 更新 backend/model/agent.go:UserSendMessageRequest.Thinking 从 bool 改为 string - 更新 backend/service/agentsvc/agent.go:AgentChat / runNormalChatFlow 适配 string 类型,新增 thinkingModeToBool 兼容旧链路 - 更新 backend/service/agentsvc/agent_newagent.go:runNewAgentGraph 接收 thinkingMode string 并注入 CommonState 3. CommonState 新增 ThinkingMode / ExecuteThinking 字段 - 更新 backend/newAgent/model/common_state.go:ThinkingMode 控制下游 thinking 行为("true" 强开 / "false" 强关 / "auto"交路由决策) - ChatNode 通过 resolveEffectiveThinking 合并前端偏好与路由决策,传递给所有下游处理函数 4. 新增真流式推送方法 - 更新 backend/newAgent/stream/emitter.go:新增 EmitStreamAssistantText / EmitStreamReasoningText,桥接 StreamReader → SSE chunk 前端:无 仓库:无
This commit is contained in:
@@ -26,18 +26,19 @@ const (
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. Route 决定后续处理路径;
|
||||
// 2. Speak 始终填写:给用户看的话;
|
||||
// 3. NeedsRoughBuild 仅在 route=execute 且满足粗排条件时为 true;
|
||||
// 4. NeedsRefineAfterRoughBuild 仅在 needs_rough_build=true 时有效;
|
||||
// 5. AllowReorder 表示是否允许打乱 suggested 任务顺序,仅用户明确授权时应为 true;
|
||||
// 6. Reason 给后端和日志看。
|
||||
// 2. NeedsRoughBuild 仅在 route=execute 且满足粗排条件时为 true;
|
||||
// 3. NeedsRefineAfterRoughBuild 仅在 needs_rough_build=true 时有效;
|
||||
// 4. AllowReorder 表示是否允许打乱 suggested 任务顺序,仅用户明确授权时应为 true;
|
||||
// 5. Thinking 表示下游 Execute 节点是否应开启深度思考;
|
||||
// 6. Raw 保留控制码原文,供日志排查;
|
||||
// 7. 用户可见内容(speak)由流式输出自然产出,不由本结构承载。
|
||||
type ChatRoutingDecision struct {
|
||||
Route ChatRoute `json:"route"`
|
||||
Speak string `json:"speak,omitempty"`
|
||||
NeedsRoughBuild bool `json:"needs_rough_build,omitempty"`
|
||||
NeedsRefineAfterRoughBuild bool `json:"needs_refine_after_rough_build,omitempty"`
|
||||
AllowReorder bool `json:"allow_reorder,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
Route ChatRoute
|
||||
NeedsRoughBuild bool
|
||||
NeedsRefineAfterRoughBuild bool
|
||||
AllowReorder bool
|
||||
Thinking bool
|
||||
Raw string
|
||||
}
|
||||
|
||||
// Normalize 统一清洗路由决策中的字符串字段。
|
||||
@@ -46,8 +47,7 @@ func (d *ChatRoutingDecision) Normalize() {
|
||||
return
|
||||
}
|
||||
d.Route = ChatRoute(strings.TrimSpace(string(d.Route)))
|
||||
d.Speak = strings.TrimSpace(d.Speak)
|
||||
d.Reason = strings.TrimSpace(d.Reason)
|
||||
d.Raw = strings.TrimSpace(d.Raw)
|
||||
}
|
||||
|
||||
// Validate 校验路由决策的最小合法性。
|
||||
@@ -67,16 +67,12 @@ func (d *ChatRoutingDecision) Validate() error {
|
||||
return fmt.Errorf("未知 route: %s", d.Route)
|
||||
}
|
||||
|
||||
// direct_reply 必须有 speak。
|
||||
if d.Route == ChatRouteDirectReply && d.Speak == "" {
|
||||
return fmt.Errorf("direct_reply 必须携带 speak")
|
||||
}
|
||||
|
||||
// 非 execute 路由不应携带粗排和粗排后微调标记,统一归一化为 false。
|
||||
if d.Route != ChatRouteExecute {
|
||||
d.NeedsRoughBuild = false
|
||||
d.NeedsRefineAfterRoughBuild = false
|
||||
d.AllowReorder = false
|
||||
d.Thinking = false
|
||||
}
|
||||
// 只有 needs_rough_build=true 时,needs_refine_after_rough_build 才有语义。
|
||||
if !d.NeedsRoughBuild {
|
||||
|
||||
@@ -30,7 +30,7 @@ const (
|
||||
FlowTerminalStatusExhausted FlowTerminalStatus = "exhausted"
|
||||
)
|
||||
|
||||
// FlowTerminalOutcome 保存“流程为什么结束”的最终结果快照。
|
||||
// FlowTerminalOutcome 保存"流程为什么结束"的最终结果快照。
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. Stage 说明终止发生在哪个阶段,便于 graph/deliver/debug 统一收口;
|
||||
@@ -97,7 +97,7 @@ type CommonState struct {
|
||||
// NeedsRoughBuild 由 Plan 节点在 plan_done 时写入,标记 Confirm 后是否需要走粗排节点。
|
||||
// 粗排节点执行完毕后会将此字段重置为 false。
|
||||
NeedsRoughBuild bool `json:"needs_rough_build,omitempty"`
|
||||
// NeedsRefineAfterRoughBuild 表示“粗排完成后是否需要立即进入微调”。
|
||||
// NeedsRefineAfterRoughBuild 表示"粗排完成后是否需要立即进入微调"。
|
||||
//
|
||||
// 说明:
|
||||
// 1. 该标记主要用于 chat->execute 的直执行链路;
|
||||
@@ -105,13 +105,21 @@ type CommonState struct {
|
||||
// 3. false 表示用户仅要求完成排入,粗排成功后可直接收口,等待后续再优化。
|
||||
NeedsRefineAfterRoughBuild bool `json:"needs_refine_after_rough_build,omitempty"`
|
||||
// AllowReorder 表示本轮是否允许打乱 suggested 任务的相对顺序。
|
||||
// 默认 false,只有用户明确说明“可以打乱顺序/顺序不重要”才会为 true。
|
||||
// 默认 false,只有用户明确说明"可以打乱顺序/顺序不重要"才会为 true。
|
||||
AllowReorder bool `json:"allow_reorder,omitempty"`
|
||||
// SuggestedOrderBaseline 保存“本轮 execute 启动前”的 suggested 任务相对顺序基线。
|
||||
// SuggestedOrderBaseline 保存"本轮 execute 启动前"的 suggested 任务相对顺序基线。
|
||||
// OrderGuard 节点会基于该基线判断微调是否破坏顺序约束。
|
||||
SuggestedOrderBaseline []int `json:"suggested_order_baseline,omitempty"`
|
||||
|
||||
// TerminalOutcome 保存“本轮流程最终如何结束”的统一收口结果。
|
||||
// ExecuteThinking 由 Chat 路由决策传入,表示 Execute 节点是否应开启深度思考。
|
||||
// 预埋字段,当前阶段 Execute 节点可自行决定是否读取。
|
||||
ExecuteThinking bool `json:"execute_thinking,omitempty"`
|
||||
|
||||
// ThinkingMode 由前端传入,控制所有下游 LLM 调用的 thinking 行为。
|
||||
// "true" 强制开启,"false" 强制关闭,"auto"(默认)交给路由决策。
|
||||
ThinkingMode string `json:"thinking_mode,omitempty"`
|
||||
|
||||
// TerminalOutcome 保存"本轮流程最终如何结束"的统一收口结果。
|
||||
// 第二轮开始,rough_build / execute / deliver 都应围绕这份快照判断收口语义。
|
||||
TerminalOutcome *FlowTerminalOutcome `json:"terminal_outcome,omitempty"`
|
||||
}
|
||||
@@ -184,12 +192,12 @@ func (s *CommonState) RejectPlan() {
|
||||
s.ClearTerminalOutcome()
|
||||
}
|
||||
|
||||
// ResetForNextRun 在“上一轮已经收口,且本轮准备开始新请求”时重置执行期临时状态。
|
||||
// ResetForNextRun 在"上一轮已经收口,且本轮准备开始新请求"时重置执行期临时状态。
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. 负责清理会污染新一轮执行的临时字段(轮次、修正计数、计划游标、粗排开关、顺序基线、终止结果);
|
||||
// 2. 不负责清理会话身份与跨轮共享数据(ConversationID/UserID/TaskClassIDs/TaskClasses/历史上下文/ScheduleState);
|
||||
// 3. 该方法是幂等操作:重复调用不会引入额外副作用,便于在“加载兜底 + chat 入口”双保险场景下复用。
|
||||
// 3. 该方法是幂等操作:重复调用不会引入额外副作用,便于在"加载兜底 + chat 入口"双保险场景下复用。
|
||||
func (s *CommonState) ResetForNextRun() {
|
||||
if s == nil {
|
||||
return
|
||||
@@ -237,7 +245,7 @@ func (s *CommonState) Done() {
|
||||
}
|
||||
}
|
||||
|
||||
// Abort 将当前流程标记为“业务语义上的主动终止”。
|
||||
// Abort 将当前流程标记为"业务语义上的主动终止"。
|
||||
//
|
||||
// 步骤说明:
|
||||
// 1. 统一写入 PhaseDone,保证 graph 后续直接进入 deliver 收口;
|
||||
@@ -255,7 +263,7 @@ func (s *CommonState) Abort(stage, code, userMessage, internalReason string) {
|
||||
s.TerminalOutcome.Normalize()
|
||||
}
|
||||
|
||||
// Exhaust 将当前流程标记为“安全边界触发的被动停止”。
|
||||
// Exhaust 将当前流程标记为"安全边界触发的被动停止"。
|
||||
func (s *CommonState) Exhaust(stage, userMessage, internalReason string) {
|
||||
s.Phase = PhaseDone
|
||||
s.TerminalOutcome = &FlowTerminalOutcome{
|
||||
@@ -289,17 +297,17 @@ func (s *CommonState) TerminalStatus() FlowTerminalStatus {
|
||||
return s.TerminalOutcome.Status
|
||||
}
|
||||
|
||||
// IsCompleted 判断当前是否属于“正常完成”。
|
||||
// IsCompleted 判断当前是否属于"正常完成"。
|
||||
func (s *CommonState) IsCompleted() bool {
|
||||
return s.TerminalStatus() == FlowTerminalStatusCompleted
|
||||
}
|
||||
|
||||
// IsAborted 判断当前是否属于“主动中止”。
|
||||
// IsAborted 判断当前是否属于"主动中止"。
|
||||
func (s *CommonState) IsAborted() bool {
|
||||
return s.TerminalStatus() == FlowTerminalStatusAborted
|
||||
}
|
||||
|
||||
// IsExhaustedTerminal 判断当前是否属于“轮次耗尽收口”。
|
||||
// IsExhaustedTerminal 判断当前是否属于"轮次耗尽收口"。
|
||||
func (s *CommonState) IsExhaustedTerminal() bool {
|
||||
return s.TerminalStatus() == FlowTerminalStatusExhausted
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user