feat: add instruction summary handling in RuntimeTraceCollector and enhance instruction assembly process

This commit is contained in:
mlogclub
2026-04-11 23:02:09 +08:00
parent be17807152
commit f1f213420d
4 changed files with 81 additions and 4 deletions
@@ -41,6 +41,20 @@ func (c *RuntimeTraceCollector) SetTooling(staticToolCodes []string, dynamicTool
c.Data.Input.ToolSearchEnabled = toolSearchEnabled
}
func (c *RuntimeTraceCollector) SetInstructionSummary(summary InstructionTraceSummary) {
if c == nil {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.Data.Instruction.SectionTitles = append([]string(nil), summary.SectionTitles...)
c.Data.Instruction.HasProjectRule = summary.HasProjectRule
c.Data.Instruction.HasGovernanceRule = summary.HasGovernanceRule
c.Data.Instruction.HasAgentRule = summary.HasAgentRule
c.Data.Instruction.HasSkillRule = summary.HasSkillRule
c.Data.Instruction.HasToolRule = summary.HasToolRule
}
func (c *RuntimeTraceCollector) AddToolItem(item ToolTraceItem) {
if c == nil {
return
@@ -41,6 +41,15 @@ type RetrieverTraceItem struct {
LatencyMs int64 `json:"latencyMs,omitempty"`
}
type InstructionTraceSummary struct {
SectionTitles []string
HasProjectRule bool
HasGovernanceRule bool
HasAgentRule bool
HasSkillRule bool
HasToolRule bool
}
type RuntimeTraceData struct {
Version string `json:"version"`
Status string `json:"status"`
@@ -54,6 +63,14 @@ type RuntimeTraceData struct {
Provider string `json:"provider,omitempty"`
Name string `json:"name,omitempty"`
} `json:"model"`
Instruction struct {
SectionTitles []string `json:"sectionTitles,omitempty"`
HasProjectRule bool `json:"hasProjectRule,omitempty"`
HasGovernanceRule bool `json:"hasGovernanceRule,omitempty"`
HasAgentRule bool `json:"hasAgentRule,omitempty"`
HasSkillRule bool `json:"hasSkillRule,omitempty"`
HasToolRule bool `json:"hasToolRule,omitempty"`
} `json:"instruction"`
Input struct {
HistoryMessageCount int `json:"historyMessageCount,omitempty"`
KnowledgeBaseIDs []int64 `json:"knowledgeBaseIds,omitempty"`
@@ -121,10 +121,21 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil
}
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
}
instructionResult := assembleAgentInstruction(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes)
if input.Collector != nil {
input.Collector.SetInstructionSummary(einocallbacks.InstructionTraceSummary{
SectionTitles: append([]string(nil), instructionResult.Summary.SectionTitles...),
HasProjectRule: instructionResult.Summary.HasProjectRule,
HasGovernanceRule: instructionResult.Summary.HasGovernanceRule,
HasAgentRule: instructionResult.Summary.HasAgentRule,
HasSkillRule: instructionResult.Summary.HasSkillRule,
HasToolRule: instructionResult.Summary.HasToolRule,
})
}
inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Name: strings.TrimSpace(input.AIAgent.Name),
Description: strings.TrimSpace(input.AIAgent.Description),
Instruction: buildAgentInstruction(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes),
Instruction: instructionResult.Text,
Model: chatModel,
ToolsConfig: adk.ToolsConfig{
ToolsNodeConfig: compose.ToolsNodeConfig{
@@ -153,7 +164,7 @@ func resolveToolSourceType(toolCode string) string {
}
}
func buildAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) string {
func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) InstructionAssemblyResult {
baseInstruction := ""
if aiAgent != nil {
baseInstruction = strings.TrimSpace(aiAgent.SystemPrompt)
@@ -191,7 +202,7 @@ func buildAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillD
`))
}
projectRoot, _ := os.Getwd()
return NewInstructionAssembler().Build(InstructionAssemblerInput{
return NewInstructionAssembler().Assemble(InstructionAssemblerInput{
ProjectRoot: projectRoot,
AgentInstruction: baseInstruction,
SkillInstruction: firstAppendixPart(appendixParts),
@@ -19,6 +19,22 @@ type InstructionAssemblerInput struct {
ProjectInstruction string
}
// InstructionAssemblySummary 描述 instruction 各组成部分的来源摘要。
type InstructionAssemblySummary struct {
SectionTitles []string
HasProjectRule bool
HasGovernanceRule bool
HasAgentRule bool
HasSkillRule bool
HasToolRule bool
}
// InstructionAssemblyResult 为 instruction 装配结果。
type InstructionAssemblyResult struct {
Text string
Summary InstructionAssemblySummary
}
var (
projectInstructionOnce sync.Once
projectInstructionText string
@@ -35,27 +51,46 @@ func NewInstructionAssembler() *InstructionAssembler {
}
func (a *InstructionAssembler) Build(input InstructionAssemblerInput) string {
return a.Assemble(input).Text
}
// Assemble 构建最终 instruction 文本及其来源摘要。
func (a *InstructionAssembler) Assemble(input InstructionAssemblerInput) InstructionAssemblyResult {
parts := make([]string, 0, 5)
summary := InstructionAssemblySummary{SectionTitles: make([]string, 0, 5)}
projectInstruction := strings.TrimSpace(input.ProjectInstruction)
if projectInstruction == "" {
projectInstruction = loadProjectInstruction(input.ProjectRoot)
}
if projectInstruction != "" {
parts = append(parts, buildInstructionSection("项目级规则", projectInstruction))
summary.HasProjectRule = true
summary.SectionTitles = append(summary.SectionTitles, "项目级规则")
}
if a != nil && strings.TrimSpace(a.governanceInstruction) != "" {
parts = append(parts, buildInstructionSection("系统治理规则", a.governanceInstruction))
summary.HasGovernanceRule = true
summary.SectionTitles = append(summary.SectionTitles, "系统治理规则")
}
if agentInstruction := strings.TrimSpace(input.AgentInstruction); agentInstruction != "" {
parts = append(parts, buildInstructionSection("Agent 规则", agentInstruction))
summary.HasAgentRule = true
summary.SectionTitles = append(summary.SectionTitles, "Agent 规则")
}
if skillInstruction := strings.TrimSpace(input.SkillInstruction); skillInstruction != "" {
parts = append(parts, buildInstructionSection("当前技能上下文", skillInstruction))
summary.HasSkillRule = true
summary.SectionTitles = append(summary.SectionTitles, "当前技能上下文")
}
if appendix := buildToolAppendix(input.ToolAppendices); appendix != "" {
parts = append(parts, buildInstructionSection("工具补充规则", appendix))
summary.HasToolRule = true
summary.SectionTitles = append(summary.SectionTitles, "工具补充规则")
}
return InstructionAssemblyResult{
Text: strings.TrimSpace(strings.Join(parts, "\n\n")),
Summary: summary,
}
return strings.TrimSpace(strings.Join(parts, "\n\n"))
}
func buildInstructionSection(title, body string) string {