Enhance skill debugging and response structure by adding skill name and allowed tool codes, and refactor related data handling
This commit is contained in:
@@ -73,6 +73,7 @@ func buildSkillDebugRunResponse(req request.SkillDebugRunRequest, summary *Summa
|
|||||||
resp.ReplyText = summary.ReplyText
|
resp.ReplyText = summary.ReplyText
|
||||||
resp.PlanReason = summary.PlanReason
|
resp.PlanReason = summary.PlanReason
|
||||||
resp.SkillRouteTrace = summary.SkillRouteTrace
|
resp.SkillRouteTrace = summary.SkillRouteTrace
|
||||||
|
resp.SkillAllowedToolCodes = append([]string(nil), summary.SkillAllowedToolCodes...)
|
||||||
resp.ToolCodes = append([]string(nil), summary.ToolCodes...)
|
resp.ToolCodes = append([]string(nil), summary.ToolCodes...)
|
||||||
resp.InvokedToolCodes = append([]string(nil), summary.InvokedToolCodes...)
|
resp.InvokedToolCodes = append([]string(nil), summary.InvokedToolCodes...)
|
||||||
resp.CheckPointID = summary.CheckPointID
|
resp.CheckPointID = summary.CheckPointID
|
||||||
|
|||||||
@@ -95,11 +95,19 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|||||||
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
|
||||||
summary.SelectedSkillCode = ""
|
summary.SelectedSkillCode = ""
|
||||||
|
summary.SelectedSkillName = ""
|
||||||
summary.SkillRouteReason = strings.TrimSpace(req.SkillRouteReason)
|
summary.SkillRouteReason = strings.TrimSpace(req.SkillRouteReason)
|
||||||
summary.SkillRouteTrace = strings.TrimSpace(req.SkillRouteTrace)
|
summary.SkillRouteTrace = strings.TrimSpace(req.SkillRouteTrace)
|
||||||
if req.SelectedSkill != nil {
|
if req.SelectedSkill != nil {
|
||||||
summary.SelectedSkillCode = strings.TrimSpace(req.SelectedSkill.Code)
|
summary.SelectedSkillCode = strings.TrimSpace(req.SelectedSkill.Code)
|
||||||
|
summary.SelectedSkillName = strings.TrimSpace(req.SelectedSkill.Name)
|
||||||
|
summary.SkillAllowedToolCodes = parseJSONArrayList(req.SelectedSkill.AllowedToolCodes)
|
||||||
|
collector.Data.Skill.Code = summary.SelectedSkillCode
|
||||||
|
collector.Data.Skill.Name = summary.SelectedSkillName
|
||||||
|
collector.Data.Skill.AllowedToolCodes = append([]string(nil), summary.SkillAllowedToolCodes...)
|
||||||
}
|
}
|
||||||
|
collector.Data.Skill.RouteReason = summary.SkillRouteReason
|
||||||
|
collector.Data.Skill.RouteTrace = summary.SkillRouteTrace
|
||||||
|
|
||||||
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, req.AIAgent, req.AIConfig, req.SelectedSkill, filteredToolDefs, req.ExtraTools, req.ExtraToolCodes, collector)
|
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, req.AIAgent, req.AIConfig, req.SelectedSkill, filteredToolDefs, req.ExtraTools, req.ExtraToolCodes, collector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -287,6 +295,22 @@ func filterToolDefinitionsBySkill(definitions []adapter.MCPToolDefinition, skill
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseJSONArraySet(raw string) map[string]struct{} {
|
func parseJSONArraySet(raw string) map[string]struct{} {
|
||||||
|
raw = strings.TrimSpace(raw)
|
||||||
|
if raw == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
items := parseJSONArrayList(raw)
|
||||||
|
if len(items) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make(map[string]struct{}, len(items))
|
||||||
|
for _, item := range items {
|
||||||
|
ret[item] = struct{}{}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseJSONArrayList(raw string) []string {
|
||||||
raw = strings.TrimSpace(raw)
|
raw = strings.TrimSpace(raw)
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
return nil
|
return nil
|
||||||
@@ -295,13 +319,13 @@ func parseJSONArraySet(raw string) map[string]struct{} {
|
|||||||
if err := json.Unmarshal([]byte(raw), &items); err != nil {
|
if err := json.Unmarshal([]byte(raw), &items); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ret := make(map[string]struct{}, len(items))
|
ret := make([]string, 0, len(items))
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
item = strings.TrimSpace(item)
|
item = strings.TrimSpace(item)
|
||||||
if item == "" {
|
if item == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret[item] = struct{}{}
|
ret = append(ret, item)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,23 +36,25 @@ type InterruptContextSummary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Summary struct {
|
type Summary struct {
|
||||||
RunID string
|
RunID string
|
||||||
Status string
|
Status string
|
||||||
ReplyText string
|
ReplyText string
|
||||||
SelectedSkillCode string
|
SelectedSkillCode string
|
||||||
SkillRouteReason string
|
SelectedSkillName string
|
||||||
SkillRouteTrace string
|
SkillRouteReason string
|
||||||
ModelName string
|
SkillRouteTrace string
|
||||||
PromptTokens int
|
SkillAllowedToolCodes []string
|
||||||
CompletionTokens int
|
ModelName string
|
||||||
HistoryMessageCount int
|
PromptTokens int
|
||||||
RetrieverCount int
|
CompletionTokens int
|
||||||
ToolCallCount int
|
HistoryMessageCount int
|
||||||
ToolCodes []string
|
RetrieverCount int
|
||||||
InvokedToolCodes []string
|
ToolCallCount int
|
||||||
CheckPointID string
|
ToolCodes []string
|
||||||
Interrupted bool
|
InvokedToolCodes []string
|
||||||
Interrupts []InterruptContextSummary
|
CheckPointID string
|
||||||
TraceData string
|
Interrupted bool
|
||||||
ErrorMessage string
|
Interrupts []InterruptContextSummary
|
||||||
|
TraceData string
|
||||||
|
ErrorMessage string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ type RetrieverTraceItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RuntimeTraceData struct {
|
type RuntimeTraceData struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
RunID string `json:"runId,omitempty"`
|
RunID string `json:"runId,omitempty"`
|
||||||
|
Skill SkillTraceData `json:"skill,omitempty"`
|
||||||
Interrupt struct {
|
Interrupt struct {
|
||||||
CheckPointID string `json:"checkPointId,omitempty"`
|
CheckPointID string `json:"checkPointId,omitempty"`
|
||||||
Items []InterruptTraceContext `json:"items,omitempty"`
|
Items []InterruptTraceContext `json:"items,omitempty"`
|
||||||
@@ -56,6 +57,14 @@ type RuntimeTraceData struct {
|
|||||||
} `json:"error"`
|
} `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SkillTraceData struct {
|
||||||
|
Code string `json:"code,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
RouteReason string `json:"routeReason,omitempty"`
|
||||||
|
RouteTrace string `json:"routeTrace,omitempty"`
|
||||||
|
AllowedToolCodes []string `json:"allowedToolCodes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type InterruptTraceContext struct {
|
type InterruptTraceContext struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
|||||||
@@ -124,24 +124,26 @@ func toSummary(summary *engine.Summary) *Summary {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ret := &Summary{
|
ret := &Summary{
|
||||||
RunID: summary.RunID,
|
RunID: summary.RunID,
|
||||||
Status: summary.Status,
|
Status: summary.Status,
|
||||||
ReplyText: summary.ReplyText,
|
ReplyText: summary.ReplyText,
|
||||||
PlannedSkillCode: strings.TrimSpace(summary.SelectedSkillCode),
|
PlannedSkillCode: strings.TrimSpace(summary.SelectedSkillCode),
|
||||||
PlanReason: strings.TrimSpace(summary.SkillRouteReason),
|
PlannedSkillName: strings.TrimSpace(summary.SelectedSkillName),
|
||||||
SkillRouteTrace: strings.TrimSpace(summary.SkillRouteTrace),
|
PlanReason: strings.TrimSpace(summary.SkillRouteReason),
|
||||||
ModelName: summary.ModelName,
|
SkillRouteTrace: strings.TrimSpace(summary.SkillRouteTrace),
|
||||||
PromptTokens: summary.PromptTokens,
|
SkillAllowedToolCodes: append([]string(nil), summary.SkillAllowedToolCodes...),
|
||||||
CompletionTokens: summary.CompletionTokens,
|
ModelName: summary.ModelName,
|
||||||
HistoryMessageCount: summary.HistoryMessageCount,
|
PromptTokens: summary.PromptTokens,
|
||||||
RetrieverCount: summary.RetrieverCount,
|
CompletionTokens: summary.CompletionTokens,
|
||||||
ToolCallCount: summary.ToolCallCount,
|
HistoryMessageCount: summary.HistoryMessageCount,
|
||||||
ToolCodes: append([]string(nil), summary.ToolCodes...),
|
RetrieverCount: summary.RetrieverCount,
|
||||||
InvokedToolCodes: append([]string(nil), summary.InvokedToolCodes...),
|
ToolCallCount: summary.ToolCallCount,
|
||||||
CheckPointID: summary.CheckPointID,
|
ToolCodes: append([]string(nil), summary.ToolCodes...),
|
||||||
Interrupted: summary.Interrupted,
|
InvokedToolCodes: append([]string(nil), summary.InvokedToolCodes...),
|
||||||
TraceData: summary.TraceData,
|
CheckPointID: summary.CheckPointID,
|
||||||
ErrorMessage: summary.ErrorMessage,
|
Interrupted: summary.Interrupted,
|
||||||
|
TraceData: summary.TraceData,
|
||||||
|
ErrorMessage: summary.ErrorMessage,
|
||||||
}
|
}
|
||||||
if len(summary.Interrupts) > 0 {
|
if len(summary.Interrupts) > 0 {
|
||||||
ret.Interrupts = make([]InterruptContextSummary, 0, len(summary.Interrupts))
|
ret.Interrupts = make([]InterruptContextSummary, 0, len(summary.Interrupts))
|
||||||
|
|||||||
@@ -37,23 +37,25 @@ type InterruptContextSummary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Summary struct {
|
type Summary struct {
|
||||||
RunID string
|
RunID string
|
||||||
Status string
|
Status string
|
||||||
ReplyText string
|
ReplyText string
|
||||||
PlannedSkillCode string
|
PlannedSkillCode string
|
||||||
PlanReason string
|
PlannedSkillName string
|
||||||
SkillRouteTrace string
|
PlanReason string
|
||||||
ModelName string
|
SkillRouteTrace string
|
||||||
PromptTokens int
|
SkillAllowedToolCodes []string
|
||||||
CompletionTokens int
|
ModelName string
|
||||||
HistoryMessageCount int
|
PromptTokens int
|
||||||
RetrieverCount int
|
CompletionTokens int
|
||||||
ToolCallCount int
|
HistoryMessageCount int
|
||||||
ToolCodes []string
|
RetrieverCount int
|
||||||
InvokedToolCodes []string
|
ToolCallCount int
|
||||||
CheckPointID string
|
ToolCodes []string
|
||||||
Interrupted bool
|
InvokedToolCodes []string
|
||||||
Interrupts []InterruptContextSummary
|
CheckPointID string
|
||||||
TraceData string
|
Interrupted bool
|
||||||
ErrorMessage string
|
Interrupts []InterruptContextSummary
|
||||||
|
TraceData string
|
||||||
|
ErrorMessage string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package skills
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -157,13 +158,40 @@ func buildSkillRoutePrompt(userMessage string, candidates []models.SkillDefiniti
|
|||||||
lines = append(lines, "")
|
lines = append(lines, "")
|
||||||
lines = append(lines, "候选 Skills:")
|
lines = append(lines, "候选 Skills:")
|
||||||
for _, item := range candidates {
|
for _, item := range candidates {
|
||||||
lines = append(lines, fmt.Sprintf("- skillCode=%s; name=%s; description=%s", strings.TrimSpace(item.Code), strings.TrimSpace(item.Name), strings.TrimSpace(item.Description)))
|
line := fmt.Sprintf("- skillCode=%s; name=%s; description=%s", strings.TrimSpace(item.Code), strings.TrimSpace(item.Name), strings.TrimSpace(item.Description))
|
||||||
|
if examples := parseSkillExamples(item.Examples); len(examples) > 0 {
|
||||||
|
line += "; examples=" + strings.Join(examples, " | ")
|
||||||
|
}
|
||||||
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
lines = append(lines, "")
|
lines = append(lines, "")
|
||||||
lines = append(lines, "请只输出一个 skillCode 或 NONE。")
|
lines = append(lines, "请只输出一个 skillCode 或 NONE。")
|
||||||
return strings.Join(lines, "\n")
|
return strings.Join(lines, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseSkillExamples(raw string) []string {
|
||||||
|
raw = strings.TrimSpace(raw)
|
||||||
|
if raw == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var items []string
|
||||||
|
if err := json.Unmarshal([]byte(raw), &items); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make([]string, 0, len(items))
|
||||||
|
for _, item := range items {
|
||||||
|
item = strings.TrimSpace(item)
|
||||||
|
if item == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret = append(ret, item)
|
||||||
|
if len(ret) >= 3 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func normalizeRouteDecision(raw string) string {
|
func normalizeRouteDecision(raw string) string {
|
||||||
raw = strings.TrimSpace(raw)
|
raw = strings.TrimSpace(raw)
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
|
|||||||
@@ -21,19 +21,20 @@ type SkillDefinitionResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SkillDebugRunResponse struct {
|
type SkillDebugRunResponse struct {
|
||||||
SkillCode string `json:"skillCode"`
|
SkillCode string `json:"skillCode"`
|
||||||
SkillName string `json:"skillName"`
|
SkillName string `json:"skillName"`
|
||||||
ReplyText string `json:"replyText"`
|
ReplyText string `json:"replyText"`
|
||||||
PlanReason string `json:"planReason"`
|
PlanReason string `json:"planReason"`
|
||||||
SkillRouteTrace string `json:"skillRouteTrace"`
|
SkillRouteTrace string `json:"skillRouteTrace"`
|
||||||
ToolCodes []string `json:"toolCodes"`
|
SkillAllowedToolCodes []string `json:"skillAllowedToolCodes"`
|
||||||
InvokedToolCodes []string `json:"invokedToolCodes"`
|
ToolCodes []string `json:"toolCodes"`
|
||||||
CheckPointID string `json:"checkPointId"`
|
InvokedToolCodes []string `json:"invokedToolCodes"`
|
||||||
Interrupted bool `json:"interrupted"`
|
CheckPointID string `json:"checkPointId"`
|
||||||
TraceData string `json:"traceData"`
|
Interrupted bool `json:"interrupted"`
|
||||||
ErrorMessage string `json:"errorMessage"`
|
TraceData string `json:"traceData"`
|
||||||
ConversationID int64 `json:"conversationId"`
|
ErrorMessage string `json:"errorMessage"`
|
||||||
AIAgentID int64 `json:"aiAgentId"`
|
ConversationID int64 `json:"conversationId"`
|
||||||
|
AIAgentID int64 `json:"aiAgentId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AgentRunLogResponse struct {
|
type AgentRunLogResponse struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user