feat: refactor agent factory to use AgentHandlerService and add buildInstructionTraceSummary helper

This commit is contained in:
mlogclub
2026-04-14 10:43:26 +08:00
parent 5ebdf1cc8e
commit 7bdd462ed5
3 changed files with 92 additions and 36 deletions
@@ -9,10 +9,8 @@ import (
einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks"
"cs-agent/internal/ai/runtime/registry" "cs-agent/internal/ai/runtime/registry"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx"
"github.com/cloudwego/eino/adk" "github.com/cloudwego/eino/adk"
einotoolsearch "github.com/cloudwego/eino/adk/middlewares/dynamictool/toolsearch"
einobasetool "github.com/cloudwego/eino/components/tool" einobasetool "github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/compose" "github.com/cloudwego/eino/compose"
) )
@@ -21,7 +19,7 @@ type AgentFactory struct {
chatModelFactory *ChatModelFactory chatModelFactory *ChatModelFactory
toolFactory *ToolFactory toolFactory *ToolFactory
instructionService *InstructionService instructionService *InstructionService
skillMiddleware *SkillMiddlewareService handlerService *AgentHandlerService
} }
// BuildCustomerServiceAgentInput 定义客服 Agent 的装配输入。 // BuildCustomerServiceAgentInput 定义客服 Agent 的装配输入。
@@ -58,7 +56,7 @@ func NewAgentFactory() *AgentFactory {
chatModelFactory: NewChatModelFactory(), chatModelFactory: NewChatModelFactory(),
toolFactory: NewToolFactory(), toolFactory: NewToolFactory(),
instructionService: NewInstructionService(nil, nil, nil, nil, nil), instructionService: NewInstructionService(nil, nil, nil, nil, nil),
skillMiddleware: NewSkillMiddlewareService(), handlerService: NewAgentHandlerService(nil),
} }
} }
@@ -77,40 +75,22 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil
} }
allTools := make([]einobasetool.BaseTool, 0, len(input.StaticTools)) allTools := make([]einobasetool.BaseTool, 0, len(input.StaticTools))
allTools = append(allTools, input.StaticTools...) allTools = append(allTools, input.StaticTools...)
handlers := make([]adk.ChatModelAgentMiddleware, 0, 2)
if len(dynamicTools) > 0 {
toolSearchHandler, toolSearchErr := einotoolsearch.New(ctx, &einotoolsearch.Config{
DynamicTools: dynamicTools,
})
if toolSearchErr != nil {
return nil, toolSearchErr
}
handlers = append(handlers, toolSearchHandler)
}
if input.SelectedSkill != nil {
skillHandler, skillErr := f.skillMiddleware.Build(ctx, input.SelectedSkill, input.InstructionToolDefinitions)
if skillErr != nil {
return nil, skillErr
}
handlers = append(handlers, skillHandler)
}
if input.Collector != nil {
toolMetadataBy := buildRuntimeTraceToolMetadata(input.DynamicMCPToolDefinitions, input.StaticToolMetadata, input.SelectedSkill)
if input.SelectedSkill != nil {
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name)
}
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
}
instructionResult := f.instructionService.Build(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes) instructionResult := f.instructionService.Build(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes)
if input.Collector != nil { handlers := make([]adk.ChatModelAgentMiddleware, 0, 3)
input.Collector.SetInstructionSummary(einocallbacks.InstructionTraceSummary{ if f.handlerService != nil {
SectionTitles: append([]string(nil), instructionResult.Summary.SectionTitles...), builtHandlers, err := f.handlerService.Build(ctx, BuildAgentHandlersInput{
HasProjectRule: instructionResult.Summary.HasProjectRule, SelectedSkill: input.SelectedSkill,
HasGovernanceRule: instructionResult.Summary.HasGovernanceRule, InstructionToolDefinitions: input.InstructionToolDefinitions,
HasAgentRule: instructionResult.Summary.HasAgentRule, DynamicToolDefinitions: input.DynamicMCPToolDefinitions,
HasSkillRule: instructionResult.Summary.HasSkillRule, DynamicTools: dynamicTools,
HasToolRule: instructionResult.Summary.HasToolRule, StaticToolMetadata: input.StaticToolMetadata,
Collector: input.Collector,
InstructionSummary: buildInstructionTraceSummary(instructionResult.Summary),
}) })
if err != nil {
return nil, err
}
handlers = append(handlers, builtHandlers...)
} }
inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Name: strings.TrimSpace(input.AIAgent.Name), Name: strings.TrimSpace(input.AIAgent.Name),
@@ -0,0 +1,65 @@
package factory
import (
"context"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks"
"cs-agent/internal/ai/runtime/registry"
"cs-agent/internal/models"
"cs-agent/internal/pkg/toolx"
"github.com/cloudwego/eino/adk"
einotoolsearch "github.com/cloudwego/eino/adk/middlewares/dynamictool/toolsearch"
einobasetool "github.com/cloudwego/eino/components/tool"
)
type AgentHandlerService struct {
skillMiddleware *SkillMiddlewareService
}
type BuildAgentHandlersInput struct {
SelectedSkill *models.SkillDefinition
InstructionToolDefinitions []einoadapter.MCPToolDefinition
DynamicToolDefinitions []einoadapter.MCPToolDefinition
DynamicTools []einobasetool.BaseTool
StaticToolMetadata map[string]registry.ToolMetadata
Collector *einocallbacks.RuntimeTraceCollector
InstructionSummary einocallbacks.InstructionTraceSummary
}
func NewAgentHandlerService(skillMiddleware *SkillMiddlewareService) *AgentHandlerService {
if skillMiddleware == nil {
skillMiddleware = NewSkillMiddlewareService()
}
return &AgentHandlerService{skillMiddleware: skillMiddleware}
}
func (s *AgentHandlerService) Build(ctx context.Context, input BuildAgentHandlersInput) ([]adk.ChatModelAgentMiddleware, error) {
handlers := make([]adk.ChatModelAgentMiddleware, 0, 3)
if len(input.DynamicTools) > 0 {
toolSearchHandler, err := einotoolsearch.New(ctx, &einotoolsearch.Config{
DynamicTools: input.DynamicTools,
})
if err != nil {
return nil, err
}
handlers = append(handlers, toolSearchHandler)
}
if input.SelectedSkill != nil {
skillHandler, err := s.skillMiddleware.Build(ctx, input.SelectedSkill, input.InstructionToolDefinitions)
if err != nil {
return nil, err
}
handlers = append(handlers, skillHandler)
}
if input.Collector != nil {
toolMetadataBy := buildRuntimeTraceToolMetadata(input.DynamicToolDefinitions, input.StaticToolMetadata, input.SelectedSkill)
if input.SelectedSkill != nil {
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name)
}
input.Collector.SetInstructionSummary(input.InstructionSummary)
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
}
return handlers, nil
}
@@ -10,6 +10,17 @@ import (
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
) )
func buildInstructionTraceSummary(summary InstructionAssemblySummary) einocallbacks.InstructionTraceSummary {
return einocallbacks.InstructionTraceSummary{
SectionTitles: append([]string(nil), summary.SectionTitles...),
HasProjectRule: summary.HasProjectRule,
HasGovernanceRule: summary.HasGovernanceRule,
HasAgentRule: summary.HasAgentRule,
HasSkillRule: summary.HasSkillRule,
HasToolRule: summary.HasToolRule,
}
}
func buildRuntimeTraceToolMetadata( func buildRuntimeTraceToolMetadata(
dynamicToolDefinitions []einoadapter.MCPToolDefinition, dynamicToolDefinitions []einoadapter.MCPToolDefinition,
staticToolMetadata map[string]registry.ToolMetadata, staticToolMetadata map[string]registry.ToolMetadata,