feat: introduce InstructionService for improved instruction assembly and refactor AgentFactory

This commit is contained in:
mlogclub
2026-04-14 10:24:35 +08:00
parent 1683ed6ed5
commit 519d5fe1e1
2 changed files with 93 additions and 46 deletions
@@ -21,13 +21,9 @@ import (
)
type AgentFactory struct {
chatModelFactory *ChatModelFactory
toolFactory *ToolFactory
instructionAssembler *InstructionAssembler
projectInstructionProvider *ProjectInstructionProvider
governanceInstructionProvider *GovernanceInstructionProvider
skillInstructionProvider *SkillInstructionProvider
toolAppendixProvider *ToolAppendixProvider
chatModelFactory *ChatModelFactory
toolFactory *ToolFactory
instructionService *InstructionService
}
// BuildCustomerServiceAgentInput 定义客服 Agent 的装配输入。
@@ -61,13 +57,9 @@ type BuildCustomerServiceAgentInput struct {
func NewAgentFactory() *AgentFactory {
return &AgentFactory{
chatModelFactory: NewChatModelFactory(),
toolFactory: NewToolFactory(),
instructionAssembler: NewInstructionAssembler(),
projectInstructionProvider: NewProjectInstructionProvider(),
governanceInstructionProvider: NewGovernanceInstructionProvider(),
skillInstructionProvider: NewSkillInstructionProvider(),
toolAppendixProvider: NewToolAppendixProvider(),
chatModelFactory: NewChatModelFactory(),
toolFactory: NewToolFactory(),
instructionService: NewInstructionService(nil, nil, nil, nil, nil),
}
}
@@ -110,7 +102,7 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil
}
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
}
instructionResult := f.assembleAgentInstruction(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes)
instructionResult := f.instructionService.Build(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes)
if input.Collector != nil {
input.Collector.SetInstructionSummary(einocallbacks.InstructionTraceSummary{
SectionTitles: append([]string(nil), instructionResult.Summary.SectionTitles...),
@@ -152,37 +144,6 @@ func (f *AgentFactory) buildSelectedSkillMiddleware(ctx context.Context, selecte
})
}
func (f *AgentFactory) assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) InstructionAssemblyResult {
baseInstruction := ""
if aiAgent != nil {
baseInstruction = strings.TrimSpace(aiAgent.SystemPrompt)
}
projectInstruction := ""
governanceInstruction := ""
skillInstruction := ""
appendixParts := buildInstructionAppendices(toolDefinitions, extraToolCodes)
if f != nil && f.projectInstructionProvider != nil {
projectInstruction = f.projectInstructionProvider.Resolve()
}
if f != nil && f.governanceInstructionProvider != nil {
governanceInstruction = f.governanceInstructionProvider.Resolve()
}
if f != nil && f.skillInstructionProvider != nil {
skillInstruction = f.skillInstructionProvider.Resolve(selectedSkill)
}
assembler := NewInstructionAssembler()
if f != nil && f.instructionAssembler != nil {
assembler = f.instructionAssembler
}
return assembler.Assemble(InstructionAssemblerInput{
AgentInstruction: baseInstruction,
GovernanceInstruction: governanceInstruction,
SkillInstruction: skillInstruction,
ToolAppendices: appendixParts,
ProjectInstruction: projectInstruction,
})
}
func buildSelectedSkillActivationInstruction(skill *models.SkillDefinition) string {
if skill == nil {
return ""
@@ -0,0 +1,86 @@
package factory
import (
"strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
"cs-agent/internal/models"
)
type InstructionService struct {
assembler *InstructionAssembler
projectInstructionProvider *ProjectInstructionProvider
governanceInstructionProvider *GovernanceInstructionProvider
skillInstructionProvider *SkillInstructionProvider
toolAppendixProvider *ToolAppendixProvider
}
func NewInstructionService(
assembler *InstructionAssembler,
projectProvider *ProjectInstructionProvider,
governanceProvider *GovernanceInstructionProvider,
skillProvider *SkillInstructionProvider,
toolProvider *ToolAppendixProvider,
) *InstructionService {
if assembler == nil {
assembler = NewInstructionAssembler()
}
if projectProvider == nil {
projectProvider = NewProjectInstructionProvider()
}
if governanceProvider == nil {
governanceProvider = NewGovernanceInstructionProvider()
}
if skillProvider == nil {
skillProvider = NewSkillInstructionProvider()
}
if toolProvider == nil {
toolProvider = NewToolAppendixProvider()
}
return &InstructionService{
assembler: assembler,
projectInstructionProvider: projectProvider,
governanceInstructionProvider: governanceProvider,
skillInstructionProvider: skillProvider,
toolAppendixProvider: toolProvider,
}
}
func (s *InstructionService) Build(
aiAgent *models.AIAgent,
selectedSkill *models.SkillDefinition,
toolDefinitions []einoadapter.MCPToolDefinition,
extraToolCodes map[string]string,
) InstructionAssemblyResult {
baseInstruction := ""
if aiAgent != nil {
baseInstruction = strings.TrimSpace(aiAgent.SystemPrompt)
}
projectInstruction := ""
governanceInstruction := ""
skillInstruction := ""
toolAppendices := make([]string, 0)
if s != nil && s.projectInstructionProvider != nil {
projectInstruction = s.projectInstructionProvider.Resolve()
}
if s != nil && s.governanceInstructionProvider != nil {
governanceInstruction = s.governanceInstructionProvider.Resolve()
}
if s != nil && s.skillInstructionProvider != nil {
skillInstruction = s.skillInstructionProvider.Resolve(selectedSkill)
}
if s != nil && s.toolAppendixProvider != nil {
toolAppendices = s.toolAppendixProvider.Build(toolDefinitions, extraToolCodes)
}
assembler := NewInstructionAssembler()
if s != nil && s.assembler != nil {
assembler = s.assembler
}
return assembler.Assemble(InstructionAssemblerInput{
AgentInstruction: baseInstruction,
GovernanceInstruction: governanceInstruction,
SkillInstruction: skillInstruction,
ToolAppendices: toolAppendices,
ProjectInstruction: projectInstruction,
})
}