feat: refactor BuildCustomerServiceAgent to use structured input for improved clarity and extensibility
This commit is contained in:
+1
-1
Submodule docs updated: 13b002c6a6...d24b234349
@@ -113,7 +113,16 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|||||||
collector.Data.Skill.RouteReason = summary.SkillRouteReason
|
collector.Data.Skill.RouteReason = summary.SkillRouteReason
|
||||||
collector.Data.Skill.RouteTrace = summary.SkillRouteTrace
|
collector.Data.Skill.RouteTrace = summary.SkillRouteTrace
|
||||||
|
|
||||||
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, req.AIAgent, req.AIConfig, req.SelectedSkill, filteredToolDefs, nil, req.ExtraTools, req.ExtraToolCodes, collector)
|
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, factory.BuildCustomerServiceAgentInput{
|
||||||
|
AIAgent: req.AIAgent,
|
||||||
|
AIConfig: req.AIConfig,
|
||||||
|
SelectedSkill: req.SelectedSkill,
|
||||||
|
InstructionToolDefinitions: filteredToolDefs,
|
||||||
|
DynamicMCPToolDefinitions: filteredToolDefs,
|
||||||
|
StaticTools: req.ExtraTools,
|
||||||
|
StaticToolCodes: req.ExtraToolCodes,
|
||||||
|
Collector: collector,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
summary.Status = "error"
|
summary.Status = "error"
|
||||||
summary.ErrorMessage = err.Error()
|
summary.ErrorMessage = err.Error()
|
||||||
@@ -241,7 +250,15 @@ func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, erro
|
|||||||
collector.Data.Input.ToolCodes = append(collector.Data.Input.ToolCodes, summary.ToolCodes...)
|
collector.Data.Input.ToolCodes = append(collector.Data.Input.ToolCodes, summary.ToolCodes...)
|
||||||
collector.Data.Model.Provider = string(req.AIConfig.Provider)
|
collector.Data.Model.Provider = string(req.AIConfig.Provider)
|
||||||
collector.Data.Model.Name = req.AIConfig.ModelName
|
collector.Data.Model.Name = req.AIConfig.ModelName
|
||||||
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, req.AIAgent, req.AIConfig, nil, nil, nil, req.ExtraTools, req.ExtraToolCodes, collector)
|
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, factory.BuildCustomerServiceAgentInput{
|
||||||
|
AIAgent: req.AIAgent,
|
||||||
|
AIConfig: req.AIConfig,
|
||||||
|
InstructionToolDefinitions: toolDefs,
|
||||||
|
DynamicMCPToolDefinitions: toolDefs,
|
||||||
|
StaticTools: req.ExtraTools,
|
||||||
|
StaticToolCodes: req.ExtraToolCodes,
|
||||||
|
Collector: collector,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
summary.Status = "error"
|
summary.Status = "error"
|
||||||
summary.ErrorMessage = err.Error()
|
summary.ErrorMessage = err.Error()
|
||||||
|
|||||||
@@ -25,6 +25,33 @@ type AgentFactory struct {
|
|||||||
instructionAssembler *InstructionAssembler
|
instructionAssembler *InstructionAssembler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildCustomerServiceAgentInput 定义客服 Agent 的装配输入。
|
||||||
|
//
|
||||||
|
// 之所以收敛成单一输入对象,而不是继续堆叠函数参数,是为了避免:
|
||||||
|
// 1. 调用点无法看懂每个位置参数的语义;
|
||||||
|
// 2. instruction 用工具、动态工具、中间件工具之间职责混淆;
|
||||||
|
// 3. 后续扩展装配项时继续拉长函数签名。
|
||||||
|
type BuildCustomerServiceAgentInput struct {
|
||||||
|
// AIAgent 为当前运行的业务 Agent 配置,提供名称、描述、系统提示词等基础信息。
|
||||||
|
AIAgent *models.AIAgent
|
||||||
|
// AIConfig 为模型配置,决定底层使用哪个 ChatModel。
|
||||||
|
AIConfig *models.AIConfig
|
||||||
|
// SelectedSkill 为当前命中的技能;为空表示本次运行未命中专项技能。
|
||||||
|
SelectedSkill *models.SkillDefinition
|
||||||
|
// InstructionToolDefinitions 用于生成 instruction 中的工具说明。
|
||||||
|
// 它描述“当前允许模型理解和使用的 MCP 工具范围”。
|
||||||
|
InstructionToolDefinitions []einoadapter.MCPToolDefinition
|
||||||
|
// DynamicMCPToolDefinitions 用于接入 Eino tool_search middleware 的动态工具集合。
|
||||||
|
// 这些工具默认不直接挂在 ToolsNode 上,而是经 tool_search 选择后再暴露给模型。
|
||||||
|
DynamicMCPToolDefinitions []einoadapter.MCPToolDefinition
|
||||||
|
// StaticTools 为当前运行时直接挂载到 ToolsNode 的固定工具,例如 Graph Tool。
|
||||||
|
StaticTools []einobasetool.BaseTool
|
||||||
|
// StaticToolCodes 为固定工具的 modelName -> toolCode 映射,用于 trace 和运行日志归因。
|
||||||
|
StaticToolCodes map[string]string
|
||||||
|
// Collector 用于收集运行链路中的 tool trace、graph trace 等调试信息。
|
||||||
|
Collector *einocallbacks.RuntimeTraceCollector
|
||||||
|
}
|
||||||
|
|
||||||
func NewAgentFactory() *AgentFactory {
|
func NewAgentFactory() *AgentFactory {
|
||||||
return &AgentFactory{
|
return &AgentFactory{
|
||||||
chatModelFactory: NewChatModelFactory(),
|
chatModelFactory: NewChatModelFactory(),
|
||||||
@@ -33,23 +60,21 @@ func NewAgentFactory() *AgentFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, aiAgent *models.AIAgent, aiConfig *models.AIConfig,
|
// BuildCustomerServiceAgent 根据装配输入构建客服 ChatModelAgent。
|
||||||
selectedSkill *models.SkillDefinition, instructionToolDefinitions []einoadapter.MCPToolDefinition, mcpToolDefinitions []einoadapter.MCPToolDefinition,
|
func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input BuildCustomerServiceAgentInput) (*einoagents.CustomerServiceAgent, error) {
|
||||||
extraTools []einobasetool.BaseTool, extraToolCodes map[string]string,
|
if input.AIAgent == nil || input.AIConfig == nil {
|
||||||
collector *einocallbacks.RuntimeTraceCollector) (*einoagents.CustomerServiceAgent, error) {
|
|
||||||
if aiAgent == nil || aiConfig == nil {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
chatModel, err := f.chatModelFactory.Build(ctx, aiConfig)
|
chatModel, err := f.chatModelFactory.Build(ctx, input.AIConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dynamicTools, err := f.toolFactory.BuildBaseToolsByDefinitions(ctx, mcpToolDefinitions)
|
dynamicTools, err := f.toolFactory.BuildBaseToolsByDefinitions(ctx, input.DynamicMCPToolDefinitions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
allTools := make([]einobasetool.BaseTool, 0, len(extraTools))
|
allTools := make([]einobasetool.BaseTool, 0, len(input.StaticTools))
|
||||||
allTools = append(allTools, extraTools...)
|
allTools = append(allTools, input.StaticTools...)
|
||||||
handlers := make([]adk.ChatModelAgentMiddleware, 0, 1)
|
handlers := make([]adk.ChatModelAgentMiddleware, 0, 1)
|
||||||
if len(dynamicTools) > 0 {
|
if len(dynamicTools) > 0 {
|
||||||
toolSearchHandler, toolSearchErr := einotoolsearch.New(ctx, &einotoolsearch.Config{
|
toolSearchHandler, toolSearchErr := einotoolsearch.New(ctx, &einotoolsearch.Config{
|
||||||
@@ -60,9 +85,9 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, aiAgent *m
|
|||||||
}
|
}
|
||||||
handlers = append(handlers, toolSearchHandler)
|
handlers = append(handlers, toolSearchHandler)
|
||||||
}
|
}
|
||||||
if collector != nil {
|
if input.Collector != nil {
|
||||||
toolMetadataBy := make(map[string]einocallbacks.ToolMetadata, len(mcpToolDefinitions)+len(extraToolCodes))
|
toolMetadataBy := make(map[string]einocallbacks.ToolMetadata, len(input.DynamicMCPToolDefinitions)+len(input.StaticToolCodes))
|
||||||
for _, item := range mcpToolDefinitions {
|
for _, item := range input.DynamicMCPToolDefinitions {
|
||||||
toolMetadataBy[item.ModelName] = einocallbacks.ToolMetadata{
|
toolMetadataBy[item.ModelName] = einocallbacks.ToolMetadata{
|
||||||
ToolCode: item.ToolCode,
|
ToolCode: item.ToolCode,
|
||||||
ServerCode: item.ServerCode,
|
ServerCode: item.ServerCode,
|
||||||
@@ -70,7 +95,7 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, aiAgent *m
|
|||||||
SourceType: "mcp",
|
SourceType: "mcp",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for modelName, toolCode := range extraToolCodes {
|
for modelName, toolCode := range input.StaticToolCodes {
|
||||||
modelName = strings.TrimSpace(modelName)
|
modelName = strings.TrimSpace(modelName)
|
||||||
toolCode = strings.TrimSpace(toolCode)
|
toolCode = strings.TrimSpace(toolCode)
|
||||||
if modelName == "" || toolCode == "" {
|
if modelName == "" || toolCode == "" {
|
||||||
@@ -94,12 +119,12 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, aiAgent *m
|
|||||||
SourceType: resolveToolSourceType(toolCode),
|
SourceType: resolveToolSourceType(toolCode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(collector, toolMetadataBy))
|
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
|
||||||
}
|
}
|
||||||
inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
|
inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
|
||||||
Name: strings.TrimSpace(aiAgent.Name),
|
Name: strings.TrimSpace(input.AIAgent.Name),
|
||||||
Description: strings.TrimSpace(aiAgent.Description),
|
Description: strings.TrimSpace(input.AIAgent.Description),
|
||||||
Instruction: buildAgentInstruction(aiAgent, selectedSkill, instructionToolDefinitions, extraToolCodes),
|
Instruction: buildAgentInstruction(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes),
|
||||||
Model: chatModel,
|
Model: chatModel,
|
||||||
ToolsConfig: adk.ToolsConfig{
|
ToolsConfig: adk.ToolsConfig{
|
||||||
ToolsNodeConfig: compose.ToolsNodeConfig{
|
ToolsNodeConfig: compose.ToolsNodeConfig{
|
||||||
|
|||||||
Reference in New Issue
Block a user