feat(trace,loop,orchestration): memory/guardrail/orchestration 真 span + 参数摘要脱敏 + Guardrail 输出侧异步(裁决 11.4.2/11.4.3/13.4.1)
- 11.4.2:三类节点首次真进图 —— memory.recall/memory.write(loop/memory.go 召回与写入点)、 guardrail.input/output(流式主路径两侧 + agent.RunStep 静音路径)、orchestration.spawn (scheduler 每次派发/收束);新增 trace.ChildSpan 让不持有 Tracer 的叶子包也能开子 span - 11.4.3(设计先行,规格先写进 design/19 §1.1):tool 节点参数摘要 —— 放行表 argValueKeys + trace.IsSecretKey 统一判据(密钥类键不给值)+ 单值 80 rune / ≤24 条 + 出图前再清洗; 前端 NodeDetail 新增「参数摘要」区,未放行键显示「值未展示」 - 13.4.1:流式主路径输出侧护栏改后台 goroutine(脱离 context、30s 兜底、不阻塞回合), 输入侧仍在模型调用前同步拦下;拦截闭环到 guardrail 节点 + 审计事件 - 拆文件:scheduler.go 加 span 后 546 行 → 编排 span 助手拆出 scheduler_spans.go(回到 492) - 契约:无帧名/事件形状变化;graph_update 节点 props 新增**可选**键(tool args_keys/args_summary、 guardrail action/allow/elapsed_ms、memory action/scope/hits/…、orchestration subagent/persona), 文档同步由主会话统一落
This commit is contained in:
1 parent
0dfad675b8
commit
b99268d019
14 files changed
+1396
-42
No files matched your search
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/trace"
|
||||
)
|
||||
|
||||
// memoryExtractTimeout 限制单次后台提取。它只管辖
|
||||
@@ -75,12 +76,21 @@ func (l *Loop) memoryBlock(ctx context.Context, messages []model.Message) string
|
||||
// 角色日常记忆(ScopePersona)属敏感项,绝不注入
|
||||
// (design/03 §5「不泄露主人敏感信息」+ 主人 2026-10-03
|
||||
// 裁决「用户习惯记忆与不敏感数据:可查、不可写」)。
|
||||
//
|
||||
// 召回本身包在一个 memory span 里(裁决 11.4.2,design/19 §1
|
||||
// 旁路节点):span 只记元数据(作用域/命中条数/注入块字节数/耗时),
|
||||
// 绝不记召回了什么内容。
|
||||
func (l *Loop) retrieveMemoryBlock(ctx context.Context, env SessionEnv, personaID, query string) (string, error) {
|
||||
if !env.Restricted() {
|
||||
return l.retriever.Inject(ctx, personaID, query, 0)
|
||||
rctx, span := l.span(ctx, spanNameMemoryRecall, trace.SpanKindMemory)
|
||||
block, err := l.retriever.Inject(rctx, personaID, query, 0)
|
||||
l.finishMemoryRecallSpan(span, "owner", 0, len(block), err)
|
||||
return block, err
|
||||
}
|
||||
results, err := l.retriever.Retrieve(ctx, personaID, query, 0)
|
||||
rctx, span := l.span(ctx, spanNameMemoryRecall, trace.SpanKindMemory)
|
||||
results, err := l.retriever.Retrieve(rctx, personaID, query, 0)
|
||||
if err != nil {
|
||||
l.finishMemoryRecallSpan(span, "restricted", 0, 0, err)
|
||||
return "", err
|
||||
}
|
||||
shared := make([]memory.Result, 0, len(results))
|
||||
@@ -90,9 +100,12 @@ func (l *Loop) retrieveMemoryBlock(ctx context.Context, env SessionEnv, personaI
|
||||
}
|
||||
}
|
||||
if len(shared) == 0 {
|
||||
l.finishMemoryRecallSpan(span, "restricted", 0, 0, nil)
|
||||
return "", nil
|
||||
}
|
||||
return formatMemoryBlock(shared, "群聊隔离"), nil
|
||||
block := formatMemoryBlock(shared, "群聊隔离")
|
||||
l.finishMemoryRecallSpan(span, "restricted", len(shared), len(block), nil)
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// sharedScope 报告 scope 是否为群聊/陌生人可查的非敏感共享域:
|
||||
@@ -278,18 +291,31 @@ func (l *Loop) extractMemoryAsync(ctx context.Context, messages []model.Message,
|
||||
// (memory.FormatSourceConversation),无条件覆盖 extractor
|
||||
// 产出值 —— 模型自由文本绝无机会落库为来源。store
|
||||
// 失败会被记录日志,绝不致命,因此一条被拒的条目无法中止一个 turn。
|
||||
//
|
||||
// 整批写入包在一个 memory span 里(裁决 11.4.2,design/19 §1 旁路节点):
|
||||
// 只记写入/失败条数与耗时,绝不记写入了什么内容;没有条目时不产生节点
|
||||
// (span 绝不宣告未运行的工作)。
|
||||
func (l *Loop) persistMemories(ctx context.Context, items []memory.MemoryItem, step int) {
|
||||
if len(items) == 0 {
|
||||
return
|
||||
}
|
||||
personaID := l.personaFor(ctx)
|
||||
source := memory.FormatSourceConversation(loopSession(ctx), loopTurn(ctx))
|
||||
wctx, span := l.span(ctx, spanNameMemoryWrite, trace.SpanKindMemory)
|
||||
written, failed := 0, 0
|
||||
for _, it := range items {
|
||||
if personaID != "" {
|
||||
it.PersonaID = personaID
|
||||
}
|
||||
it.SourceConversation = source
|
||||
if _, err := l.memory.Add(ctx, it); err != nil {
|
||||
if _, err := l.memory.Add(wctx, it); err != nil {
|
||||
failed++
|
||||
l.log.Warn("memory store", "step", step, "error", err)
|
||||
continue
|
||||
}
|
||||
written++
|
||||
}
|
||||
l.finishMemoryWriteSpan(span, written, failed, nil)
|
||||
}
|
||||
|
||||
// queryFromMessages 从对话导出检索查询:最后一个用户
|
||||
|
||||
Reference in new issue
Block a user