feat: Support for Chat Flow & Agent Support for binding a single chat flow (#765)
Co-authored-by: Yu Yang <72337138+tomasyu985@users.noreply.github.com> Co-authored-by: zengxiaohui <csu.zengxiaohui@gmail.com> Co-authored-by: lijunwen.gigoo <lijunwen.gigoo@bytedance.com> Co-authored-by: lvxinyu.1117 <lvxinyu.1117@bytedance.com> Co-authored-by: liuyunchao.0510 <liuyunchao.0510@bytedance.com> Co-authored-by: haozhenfei <37089575+haozhenfei@users.noreply.github.com> Co-authored-by: July <jiangxujin@bytedance.com> Co-authored-by: tecvan-fe <fanwenjie.fe@bytedance.com>
This commit is contained in:
@ -26,6 +26,8 @@ import (
|
||||
"github.com/cloudwego/eino/schema"
|
||||
|
||||
workflowModel "github.com/coze-dev/coze-studio/backend/api/model/crossdomain/workflow"
|
||||
workflowapimodel "github.com/coze-dev/coze-studio/backend/api/model/workflow"
|
||||
crossmessage "github.com/coze-dev/coze-studio/backend/crossdomain/contract/message"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
||||
@ -62,6 +64,8 @@ func (i *impl) SyncExecute(ctx context.Context, config workflowModel.ExecuteConf
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
isApplicationWorkflow := wfEntity.AppID != nil
|
||||
if isApplicationWorkflow && config.Mode == workflowModel.ExecuteModeRelease {
|
||||
err = i.checkApplicationWorkflowReleaseVersion(ctx, *wfEntity.AppID, config.ConnectorID, config.ID, config.Version)
|
||||
@ -207,6 +211,8 @@ func (i *impl) AsyncExecute(ctx context.Context, config workflowModel.ExecuteCon
|
||||
return 0, err
|
||||
}
|
||||
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
isApplicationWorkflow := wfEntity.AppID != nil
|
||||
if isApplicationWorkflow && config.Mode == workflowModel.ExecuteModeRelease {
|
||||
err = i.checkApplicationWorkflowReleaseVersion(ctx, *wfEntity.AppID, config.ConnectorID, config.ID, config.Version)
|
||||
@ -292,6 +298,8 @@ func (i *impl) AsyncExecuteNode(ctx context.Context, nodeID string, config workf
|
||||
return 0, err
|
||||
}
|
||||
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
isApplicationWorkflow := wfEntity.AppID != nil
|
||||
if isApplicationWorkflow && config.Mode == workflowModel.ExecuteModeRelease {
|
||||
err = i.checkApplicationWorkflowReleaseVersion(ctx, *wfEntity.AppID, config.ConnectorID, config.ID, config.Version)
|
||||
@ -300,6 +308,30 @@ func (i *impl) AsyncExecuteNode(ctx context.Context, nodeID string, config workf
|
||||
}
|
||||
}
|
||||
|
||||
historyRounds := int64(0)
|
||||
if config.WorkflowMode == workflowapimodel.WorkflowMode_ChatFlow {
|
||||
|
||||
historyRounds, err = getHistoryRoundsFromNode(ctx, wfEntity, nodeID, i.repo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if historyRounds > 0 {
|
||||
messages, scMessages, err := i.prefetchChatHistory(ctx, config, historyRounds)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "failed to prefetch chat history: %v", err)
|
||||
}
|
||||
|
||||
if len(messages) > 0 {
|
||||
config.ConversationHistory = messages
|
||||
}
|
||||
|
||||
if len(scMessages) > 0 {
|
||||
config.ConversationHistorySchemaMessages = scMessages
|
||||
}
|
||||
|
||||
}
|
||||
c := &vo.Canvas{}
|
||||
if err = sonic.UnmarshalString(wfEntity.Canvas, c); err != nil {
|
||||
return 0, fmt.Errorf("failed to unmarshal canvas: %w", err)
|
||||
@ -375,6 +407,8 @@ func (i *impl) StreamExecute(ctx context.Context, config workflowModel.ExecuteCo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
isApplicationWorkflow := wfEntity.AppID != nil
|
||||
if isApplicationWorkflow && config.Mode == workflowModel.ExecuteModeRelease {
|
||||
err = i.checkApplicationWorkflowReleaseVersion(ctx, *wfEntity.AppID, config.ConnectorID, config.ID, config.Version)
|
||||
@ -383,6 +417,29 @@ func (i *impl) StreamExecute(ctx context.Context, config workflowModel.ExecuteCo
|
||||
}
|
||||
}
|
||||
|
||||
historyRounds := int64(0)
|
||||
if config.WorkflowMode == workflowapimodel.WorkflowMode_ChatFlow {
|
||||
historyRounds, err = i.calculateMaxChatHistoryRounds(ctx, wfEntity, i.repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if historyRounds > 0 {
|
||||
messages, scMessages, err := i.prefetchChatHistory(ctx, config, historyRounds)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "failed to prefetch chat history: %v", err)
|
||||
}
|
||||
|
||||
if len(messages) > 0 {
|
||||
config.ConversationHistory = messages
|
||||
}
|
||||
|
||||
if len(scMessages) > 0 {
|
||||
config.ConversationHistorySchemaMessages = scMessages
|
||||
}
|
||||
|
||||
}
|
||||
c := &vo.Canvas{}
|
||||
if err = sonic.UnmarshalString(wfEntity.Canvas, c); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal canvas: %w", err)
|
||||
@ -718,6 +775,7 @@ func (i *impl) AsyncResume(ctx context.Context, req *entity.ResumeRequest, confi
|
||||
config.AppID = wfExe.AppID
|
||||
config.AgentID = wfExe.AgentID
|
||||
config.CommitID = wfExe.CommitID
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
if config.ConnectorID == 0 {
|
||||
config.ConnectorID = wfExe.ConnectorID
|
||||
@ -859,6 +917,7 @@ func (i *impl) StreamResume(ctx context.Context, req *entity.ResumeRequest, conf
|
||||
config.AppID = wfExe.AppID
|
||||
config.AgentID = wfExe.AgentID
|
||||
config.CommitID = wfExe.CommitID
|
||||
config.WorkflowMode = wfEntity.Mode
|
||||
|
||||
if config.ConnectorID == 0 {
|
||||
config.ConnectorID = wfExe.ConnectorID
|
||||
@ -937,3 +996,73 @@ func (i *impl) checkApplicationWorkflowReleaseVersion(ctx context.Context, appID
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const maxHistoryRounds int64 = 30
|
||||
|
||||
func (i *impl) calculateMaxChatHistoryRounds(ctx context.Context, wfEntity *entity.Workflow, repo workflow.Repository) (int64, error) {
|
||||
if wfEntity == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
maxRounds, err := getMaxHistoryRoundsRecursively(ctx, wfEntity, repo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return min(maxRounds, maxHistoryRounds), nil
|
||||
}
|
||||
|
||||
func (i *impl) prefetchChatHistory(ctx context.Context, config workflowModel.ExecuteConfig, historyRounds int64) ([]*crossmessage.WfMessage, []*schema.Message, error) {
|
||||
convID := config.ConversationID
|
||||
agentID := config.AgentID
|
||||
appID := config.AppID
|
||||
userID := config.Operator
|
||||
sectionID := config.SectionID
|
||||
if sectionID == nil {
|
||||
logs.CtxWarnf(ctx, "SectionID is nil, skipping chat history")
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
if convID == nil || *convID == 0 {
|
||||
logs.CtxWarnf(ctx, "ConversationID is 0 or nil, skipping chat history")
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
var resolvedAppID int64
|
||||
if appID != nil {
|
||||
resolvedAppID = *appID
|
||||
} else if agentID != nil {
|
||||
resolvedAppID = *agentID
|
||||
} else {
|
||||
logs.CtxWarnf(ctx, "AppID and AgentID are both nil, skipping chat history")
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
runIdsReq := &crossmessage.GetLatestRunIDsRequest{
|
||||
ConversationID: *convID,
|
||||
AppID: resolvedAppID,
|
||||
UserID: userID,
|
||||
Rounds: historyRounds + 1,
|
||||
SectionID: *sectionID,
|
||||
}
|
||||
|
||||
runIds, err := crossmessage.DefaultSVC().GetLatestRunIDs(ctx, runIdsReq)
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "failed to get latest run ids: %v", err)
|
||||
return nil, nil, nil
|
||||
}
|
||||
if len(runIds) <= 1 {
|
||||
return []*crossmessage.WfMessage{}, []*schema.Message{}, nil
|
||||
}
|
||||
runIds = runIds[1:]
|
||||
|
||||
response, err := crossmessage.DefaultSVC().GetMessagesByRunIDs(ctx, &crossmessage.GetMessagesByRunIDsRequest{
|
||||
ConversationID: *convID,
|
||||
RunIDs: runIds,
|
||||
})
|
||||
if err != nil {
|
||||
logs.CtxErrorf(ctx, "failed to get messages by run ids: %v", err)
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
return response.Messages, response.SchemaMessages, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user