From 7df7384b210f3304b9bdfd06bfb8b47f0407edb4 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Tue, 7 Jul 2026 17:22:08 +0800 Subject: [PATCH] Go: refactor UUID functions (#16695) As title --------- Signed-off-by: Jin Hai --- cmd/ragflow_server.go | 4 ++-- internal/admin/handler.go | 2 +- internal/admin/service.go | 2 +- internal/agent/canvas/runner.go | 7 +++--- internal/common/app_name.go | 11 --------- internal/dao/connector.go | 8 +++---- internal/dao/file.go | 19 +++++----------- internal/dao/file_commit.go | 9 -------- internal/dao/ingestion.go | 3 ++- internal/dao/skill_search_config.go | 10 ++------- internal/dao/skill_space.go | 8 ------- internal/entity/models/302ai.go | 2 +- internal/harness/graph/graph/compiled.go | 5 +++-- internal/ingestion/ingestion_service.go | 3 ++- internal/service/agent.go | 20 +++++------------ internal/service/agent_sessions.go | 4 ++-- internal/service/api_token.go | 4 ++-- internal/service/bot_completion.go | 5 +++-- internal/service/chat.go | 3 ++- internal/service/chat_channel.go | 5 +++-- internal/service/chat_session.go | 10 ++++----- internal/service/chunk/chunk.go | 2 +- internal/service/connector.go | 7 +++--- internal/service/dataset.go | 6 ++--- internal/service/deep_researcher.go | 4 ++-- internal/service/document.go | 13 +++++------ internal/service/file.go | 13 +++-------- internal/service/file2document.go | 4 ++-- internal/service/file_commit.go | 13 +++-------- internal/service/mcp.go | 4 ++-- internal/service/memory.go | 3 ++- internal/service/memory_message_service.go | 4 ++-- internal/service/search.go | 3 ++- internal/service/skill_search.go | 6 ----- internal/service/skill_space.go | 14 ++++-------- internal/service/tenant.go | 5 +++-- internal/syncer/syncer.go | 3 ++- internal/utility/token.go | 26 +++++++++++----------- 38 files changed, 104 insertions(+), 170 deletions(-) diff --git a/cmd/ragflow_server.go b/cmd/ragflow_server.go index 2d3c36f7e..57eddf28b 100644 --- a/cmd/ragflow_server.go +++ b/cmd/ragflow_server.go @@ -285,12 +285,12 @@ func main() { } case "ingestor": if serverName == "" { - uuid := common.GenerateUUID() + uuid := utility.GenerateUUID() serverName = fmt.Sprintf("ingestor_server_%s", uuid) } case "syncer": if serverName == "" { - uuid := common.GenerateUUID() + uuid := utility.GenerateUUID() serverName = fmt.Sprintf("syncer_server_%s", uuid) } default: diff --git a/internal/admin/handler.go b/internal/admin/handler.go index b278ba64e..a4d0fd724 100644 --- a/internal/admin/handler.go +++ b/internal/admin/handler.go @@ -1158,7 +1158,7 @@ func (h *Handler) ShutdownIngestor(c *gin.Context) { return } - taskID := common.GenerateUUID() + taskID := utility.GenerateUUID() //ingestionManager.SubmitTask(&common.TaskAssignment{ // TaskId: taskID, // TaskType: "SHUTDOWN", diff --git a/internal/admin/service.go b/internal/admin/service.go index bcf98e6c2..d4df67bc5 100644 --- a/internal/admin/service.go +++ b/internal/admin/service.go @@ -972,7 +972,7 @@ func (s *Service) GenerateUserAPIToken(username string) (map[string]interface{}, // 3. Generate API token key := utility.GenerateAPIToken() - beta := utility.GenerateBetaAPIToken(key) + beta := utility.GenerateBetaAPIToken() apiToken := &entity.APIToken{ TenantID: tenantID, diff --git a/internal/agent/canvas/runner.go b/internal/agent/canvas/runner.go index 0640d00b9..638048872 100644 --- a/internal/agent/canvas/runner.go +++ b/internal/agent/canvas/runner.go @@ -52,12 +52,11 @@ import ( "encoding/json" "errors" "fmt" + "ragflow/internal/utility" "runtime/debug" - "strings" "sync" "time" - "github.com/google/uuid" "go.uber.org/zap" "ragflow/internal/agent/runtime" @@ -250,13 +249,13 @@ func (r *Runner) Run( // message_id is generated per-run so the front-end can correlate // all events for a single user turn. task_id is the published // version id (if available) or a per-run UUID. - messageID := strings.ReplaceAll(uuid.New().String(), "-", "") + messageID := utility.GenerateToken() taskID := "" if v, ok := root["version_id"].(string); ok && v != "" { taskID = v } if taskID == "" { - taskID = strings.ReplaceAll(uuid.New().String(), "-", "") + taskID = utility.GenerateToken() } // Inject the output channel + metadata so the RunFunc can emit diff --git a/internal/common/app_name.go b/internal/common/app_name.go index a81ab4dd5..b1ff8a6b5 100644 --- a/internal/common/app_name.go +++ b/internal/common/app_name.go @@ -21,8 +21,6 @@ import ( "path" "regexp" "strings" - - "github.com/google/uuid" ) // splitNameCounter splits a filename into base name and counter @@ -114,12 +112,3 @@ func ValidateName(name string) error { return nil } - -// GenerateUUID generates a UUID without dashes -func GenerateUUID() string { - newID := strings.ReplaceAll(uuid.New().String(), "-", "") - if len(newID) > 32 { - newID = newID[:32] - } - return newID -} diff --git a/internal/dao/connector.go b/internal/dao/connector.go index a5a4491ea..00b484742 100644 --- a/internal/dao/connector.go +++ b/internal/dao/connector.go @@ -18,8 +18,8 @@ package dao import ( "errors" - "ragflow/internal/common" "ragflow/internal/entity" + "ragflow/internal/utility" "time" "gorm.io/gorm" @@ -121,7 +121,7 @@ func (dao *ConnectorDAO) LinkDatasetConnectors(kbID string, connectors []Dataset } if err := tx.Create(&entity.Connector2Kb{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), ConnectorID: connector.ID, KbID: kbID, AutoParse: autoParse, @@ -323,7 +323,7 @@ func createRebuildSyncLog(tx *gorm.DB, connectorID, kbID, taskType string, reind } now := time.Now().Local() return tx.Create(&entity.SyncLogs{ - ID: generateUUID(), + ID: utility.GenerateToken(), ConnectorID: connectorID, KbID: kbID, TaskType: taskType, @@ -368,7 +368,7 @@ func scheduleConnectorTask(tx *gorm.DB, connectorID, kbID, taskType string, rein } now := time.Now().Local() return tx.Create(&entity.SyncLogs{ - ID: generateUUID(), + ID: utility.GenerateToken(), ConnectorID: connectorID, KbID: kbID, TaskType: taskType, diff --git a/internal/dao/file.go b/internal/dao/file.go index 9531cc8aa..7038c4707 100644 --- a/internal/dao/file.go +++ b/internal/dao/file.go @@ -20,9 +20,8 @@ import ( "fmt" "log" "ragflow/internal/entity" + "ragflow/internal/utility" "strings" - - "github.com/google/uuid" ) // FileDAO file data access object @@ -92,7 +91,7 @@ func (dao *FileDAO) GetRootFolder(tenantID string) (*entity.File, error) { } // Create root folder if not exists - fileID := generateUUID() + fileID := utility.GenerateToken() file = entity.File{ ID: fileID, ParentID: fileID, @@ -285,7 +284,7 @@ func (dao *FileDAO) GetIDListByID(id string, names []string, count int, res []st // CreateFolder creates a folder in the database func (dao *FileDAO) CreateFolder(parentID, tenantID, name, fileType string) (*entity.File, error) { file := &entity.File{ - ID: generateUUID(), + ID: utility.GenerateToken(), ParentID: parentID, TenantID: tenantID, CreatedBy: tenantID, @@ -363,12 +362,6 @@ func (dao *FileDAO) GetDatasetIDByFileID(fileID string) ([]string, error) { return datasetIDs, nil } -// generateUUID generates a UUID -func generateUUID() string { - id := uuid.New().String() - return strings.ReplaceAll(id, "-", "") -} - // reparentAndDeleteFolder safely removes a duplicate folder by first // reparenting any child records to the kept folder, then hard-deleting // the duplicate row. This prevents orphaned children when cleaning up @@ -477,7 +470,7 @@ func (dao *FileDAO) newAFileFromDataset(tenantID, name, parentID string) (*entit return existingFiles[0], nil } - fileID := generateUUID() + fileID := utility.GenerateToken() file := &entity.File{ ID: fileID, ParentID: parentID, @@ -519,7 +512,7 @@ func (dao *FileDAO) addFileFromKB(doc *entity.Document, datasetFolderID, tenantI docLocation = *doc.Location } - fileID := generateUUID() + fileID := utility.GenerateToken() file := &entity.File{ ID: fileID, ParentID: datasetFolderID, @@ -536,7 +529,7 @@ func (dao *FileDAO) addFileFromKB(doc *entity.Document, datasetFolderID, tenantI return err } - f2dID := generateUUID() + f2dID := utility.GenerateToken() f2d := &entity.File2Document{ ID: f2dID, FileID: &fileID, diff --git a/internal/dao/file_commit.go b/internal/dao/file_commit.go index e8ab24122..974de48a3 100644 --- a/internal/dao/file_commit.go +++ b/internal/dao/file_commit.go @@ -18,9 +18,6 @@ package dao import ( "ragflow/internal/entity" - "strings" - - "github.com/google/uuid" ) // FileCommitDAO file commit data access object @@ -146,9 +143,3 @@ func (dao *FileCommitItemDAO) GetByCommitIDAndFileID(commitID, fileID string) (* } return &item, nil } - -// generateCommitUUID generates a UUID for commit/commit_item IDs -func generateCommitUUID() string { - id := uuid.New().String() - return strings.ReplaceAll(id, "-", "") -} diff --git a/internal/dao/ingestion.go b/internal/dao/ingestion.go index 15ff32966..4f43def60 100644 --- a/internal/dao/ingestion.go +++ b/internal/dao/ingestion.go @@ -21,6 +21,7 @@ import ( "fmt" "ragflow/internal/common" "ragflow/internal/entity" + "ragflow/internal/utility" ) type IngestionTaskDAO struct{} @@ -70,7 +71,7 @@ func (dao *IngestionTaskDAO) CheckAndCreate(ingestionTask *entity.IngestionTask) } } else { // create ingestion task - ingestionTask.ID = common.GenerateUUID() + ingestionTask.ID = utility.GenerateUUID() if err = tx.Create(ingestionTask).Error; err != nil { tx.Rollback() return nil, err diff --git a/internal/dao/skill_search_config.go b/internal/dao/skill_search_config.go index 16c01d56e..8a3939de1 100644 --- a/internal/dao/skill_search_config.go +++ b/internal/dao/skill_search_config.go @@ -18,9 +18,8 @@ package dao import ( "ragflow/internal/entity" + "ragflow/internal/utility" "strings" - - "github.com/google/uuid" ) // SkillSearchConfigDAO data access object for skill search config @@ -129,7 +128,7 @@ func (dao *SkillSearchConfigDAO) CreateWithTenantSpace(tenantID, spaceID, embdID } defaultConfig := &entity.SkillSearchConfig{ - ID: generateID(), + ID: utility.GenerateUUID(), TenantID: tenantID, SpaceID: spaceID, EmbdID: embdID, @@ -183,8 +182,3 @@ func (dao *SkillSearchConfigDAO) UpdateByTenantAndEmbdID(tenantID, spaceID, embd func (dao *SkillSearchConfigDAO) Delete(id string) error { return DB.Model(&entity.SkillSearchConfig{}).Where("id = ?", id).Update("status", "0").Error } - -// generateID generates a unique ID -func generateID() string { - return strings.ReplaceAll(uuid.New().String(), "-", "")[:32] -} diff --git a/internal/dao/skill_space.go b/internal/dao/skill_space.go index c8557521f..937dfdb94 100644 --- a/internal/dao/skill_space.go +++ b/internal/dao/skill_space.go @@ -18,9 +18,6 @@ package dao import ( "ragflow/internal/entity" - "strings" - - "github.com/google/uuid" ) // SkillSpaceDAO data access object for skills space @@ -132,8 +129,3 @@ func (dao *SkillSpaceDAO) CountByTenant(tenantID string) (int64, error) { err := DB.Model(&entity.SkillSpace{}).Where("tenant_id = ? AND status = ?", tenantID, entity.SpaceStatusActive).Count(&count).Error return count, err } - -// generateSpaceID generates a unique ID -func generateSpaceID() string { - return strings.ReplaceAll(uuid.New().String(), "-", "")[:32] -} diff --git a/internal/entity/models/302ai.go b/internal/entity/models/302ai.go index fb64492a7..85910db12 100644 --- a/internal/entity/models/302ai.go +++ b/internal/entity/models/302ai.go @@ -324,7 +324,7 @@ func (a *AI302Model) ChatStreamlyWithSender(modelName string, messages []Message return fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body)) } - if _, err := ParseSSEStream[map[string]interface{}](resp.Body, func(event map[string]interface{}) error { + if _, err = ParseSSEStream[map[string]interface{}](resp.Body, func(event map[string]interface{}) error { choices, ok := event["choices"].([]interface{}) if !ok || len(choices) == 0 { return nil diff --git a/internal/harness/graph/graph/compiled.go b/internal/harness/graph/graph/compiled.go index 177acbe2d..c6ca482d0 100644 --- a/internal/harness/graph/graph/compiled.go +++ b/internal/harness/graph/graph/compiled.go @@ -6,9 +6,10 @@ import ( "fmt" "sync" - "github.com/google/uuid" "ragflow/internal/harness/graph/constants" "ragflow/internal/harness/graph/types" + + "github.com/google/uuid" ) // CompiledStateGraph represents a compiled state graph with full subgraph support. @@ -229,5 +230,5 @@ func buildTaskPath(namespace, subgraphName string) string { // generateCheckpointID generates a new checkpoint ID. func generateCheckpointID() string { - return "cp_" + uuid.New().String() + return "ckp_" + uuid.New().String() } diff --git a/internal/ingestion/ingestion_service.go b/internal/ingestion/ingestion_service.go index 627ed9694..10d7d7936 100644 --- a/internal/ingestion/ingestion_service.go +++ b/internal/ingestion/ingestion_service.go @@ -24,6 +24,7 @@ import ( "ragflow/internal/engine" "ragflow/internal/entity" "ragflow/internal/ingestion/pipeline" + "ragflow/internal/utility" "sync" "time" @@ -87,7 +88,7 @@ type TaskContext struct { func NewIngestor(name string, maxConcurrency int32, supportedTypes []string) *Ingestor { ctx, cancel := context.WithCancel(context.Background()) - id := common.GenerateUUID() + id := utility.GenerateUUID() return &Ingestor{ id: id, name: name, diff --git a/internal/service/agent.go b/internal/service/agent.go index d83071642..b55f0a041 100644 --- a/internal/service/agent.go +++ b/internal/service/agent.go @@ -21,13 +21,13 @@ import ( "encoding/json" "errors" "fmt" + "ragflow/internal/utility" "reflect" "strings" "sync" "time" "github.com/cloudwego/eino/compose" - "github.com/google/uuid" "go.uber.org/zap" "gorm.io/gorm" @@ -43,14 +43,6 @@ import ( dslpkg "ragflow/internal/agent/dsl" ) -// genID32 returns a 32-char UUID-derived primary key suitable for the -// user_canvas and user_canvas_version tables. The format matches Python -// uuid.uuid4().hex used by the original DAO and keeps existing rows -// joinable across Python and Go writers. -func genID32() string { - return strings.ReplaceAll(uuid.New().String(), "-", "")[:32] -} - // webhookPayloadKey is the unexported context key RunAgent reads to // inject root["webhook_payload"]. Only the AgentService.RunAgentWithWebhook // public wrapper sets it; the chat / agent-run paths leave it absent so @@ -358,7 +350,7 @@ func (s *AgentService) CreateAgent(ctx context.Context, req *CreateAgentRequest) // no-op when graph.nodes is already non-empty. req.DSL = dslpkg.NormalizeForCanvas(req.DSL) row := &entity.UserCanvas{ - ID: genID32(), + ID: utility.GenerateUUID(), UserID: req.UserID, Title: req.Title, Description: req.Description, @@ -575,7 +567,7 @@ func (s *AgentService) PublishAgent(ctx context.Context, userID, canvasID string } } row := &entity.UserCanvasVersion{ - ID: genID32(), + ID: utility.GenerateUUID(), UserCanvasID: canvasID, Title: title, Description: description, @@ -606,7 +598,7 @@ func (s *AgentService) saveOrReplaceVersion(ctx context.Context, userID, canvasI } versionTitle := buildVersionTitle(nickname, title, time.Now()) return s.versionDAO.SaveOrReplaceLatest(dao.SaveOrReplaceLatestVersionOptions{ - NewID: genID32(), + NewID: utility.GenerateUUID(), UserCanvasID: canvasID, Title: &versionTitle, Description: description, @@ -713,7 +705,7 @@ func (s *AgentService) RunAgent(ctx context.Context, userID, canvasID, sessionID return nil, err } if sessionID == "" { - sessionID = strings.ReplaceAll(uuid.New().String(), "-", "") + sessionID = utility.GenerateToken() } // Load the version row up front so the run is bound to a real DSL. @@ -1256,7 +1248,7 @@ func (s *AgentService) persistAgentRunSession(agentID, sessionID, messageID stri messages := parseAgentSessionMessages(session.Message) now := time.Now().Unix() if text := stringifyAgentUserInput(userInput); text != "" { - messages = append(messages, map[string]interface{}{"role": "user", "content": text, "id": strings.ReplaceAll(uuid.New().String(), "-", ""), "created_at": now}) + messages = append(messages, map[string]interface{}{"role": "user", "content": text, "id": utility.GenerateToken(), "created_at": now}) } messages = append(messages, map[string]interface{}{"role": "assistant", "content": answer, "id": messageID, "created_at": now}) if raw, err := json.Marshal(messages); err == nil { diff --git a/internal/service/agent_sessions.go b/internal/service/agent_sessions.go index c2f3e6de3..c29cb9b7d 100644 --- a/internal/service/agent_sessions.go +++ b/internal/service/agent_sessions.go @@ -20,12 +20,12 @@ import ( "encoding/json" "errors" "fmt" + "ragflow/internal/utility" "sort" "strconv" "strings" "time" - "github.com/google/uuid" "gorm.io/gorm" "ragflow/internal/common" @@ -736,7 +736,7 @@ func (s *AgentService) CreateAgentSession(req *CreateAgentSessionRequest) (*enti sourcePtr = &req.Source } - id := strings.ReplaceAll(uuid.New().String(), "-", "")[:32] + id := utility.GenerateUUID() // CreateTime / UpdateTime / CreateDate / UpdateDate are filled in // by entity.BaseModel.BeforeCreate when the DAO Create() call runs, diff --git a/internal/service/api_token.go b/internal/service/api_token.go index 1fe936abb..7c9dd33b4 100644 --- a/internal/service/api_token.go +++ b/internal/service/api_token.go @@ -45,7 +45,7 @@ func (s *SystemService) ListAPIKeys(tenantID string) ([]*APIKeyResponse, error) for i, key := range keys { beta := key.Beta if beta == nil || *beta == "" { - generatedBeta := utility.GenerateBetaAPIToken(utility.GenerateAPIToken()) + generatedBeta := utility.GenerateBetaAPIToken() if err = dao.DB.Model(&entity.APIToken{}). Where("tenant_id = ? AND token = ?", tenantID, key.Token). Updates(map[string]interface{}{ @@ -84,7 +84,7 @@ func (s *SystemService) CreateAPIKey(tenantID string, req *CreateAPIKeyRequest) // key: "ragflow-" + secrets.token_urlsafe(32) APIToken := utility.GenerateAPIToken() // beta: generate_confirmation_token().replace("ragflow-", "")[:32] - betaAPIKey := utility.GenerateBetaAPIToken(utility.GenerateAPIToken()) + betaAPIKey := utility.GenerateBetaAPIToken() APIKeyData := &entity.APIToken{ TenantID: tenantID, diff --git a/internal/service/bot_completion.go b/internal/service/bot_completion.go index 647aba838..da33565f4 100644 --- a/internal/service/bot_completion.go +++ b/internal/service/bot_completion.go @@ -38,6 +38,7 @@ import ( "encoding/json" "errors" "net/http" + "ragflow/internal/utility" "time" "go.uber.org/zap" @@ -327,12 +328,12 @@ func (s *BotService) ChatbotCompletion( }, }) session = &entity.API4Conversation{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DialogID: dialogID, UserID: tenantID, Message: seedMsg, } - if err := s.api4ConversationDAO.Create(session); err != nil { + if err = s.api4ConversationDAO.Create(session); err != nil { return nil, common.CodeServerError, err } } diff --git a/internal/service/chat.go b/internal/service/chat.go index 85aaace71..e304c7d60 100644 --- a/internal/service/chat.go +++ b/internal/service/chat.go @@ -22,6 +22,7 @@ import ( "fmt" "ragflow/internal/common" "ragflow/internal/entity" + "ragflow/internal/utility" "strings" "unicode/utf8" @@ -415,7 +416,7 @@ func buildCreateChatEntity(req map[string]interface{}, tenantID string) *entity. } chat := &entity.Chat{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), TenantID: tenantID, Name: &name, Description: &description, diff --git a/internal/service/chat_channel.go b/internal/service/chat_channel.go index 7f910c306..f047e300f 100644 --- a/internal/service/chat_channel.go +++ b/internal/service/chat_channel.go @@ -17,6 +17,7 @@ package service import ( "errors" "fmt" + "ragflow/internal/utility" "ragflow/internal/common" "ragflow/internal/dao" @@ -42,7 +43,7 @@ func (s *ChatChannelService) Insert(channel *entity.ChatChannel) error { return errors.New("channel is nil") } if channel.ID == "" { - channel.ID = common.GenerateUUID() + channel.ID = utility.GenerateUUID() } if channel.Status == 0 { channel.Status = 1 @@ -75,7 +76,7 @@ func (s *ChatChannelService) CreateChatChannel(tenantID, name, channelType strin } } row := &entity.ChatChannel{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), TenantID: tenantID, Name: name, Channel: channelType, diff --git a/internal/service/chat_session.go b/internal/service/chat_session.go index 7e14b3fe7..cf785f6c0 100644 --- a/internal/service/chat_session.go +++ b/internal/service/chat_session.go @@ -26,6 +26,7 @@ import ( "ragflow/internal/common" "ragflow/internal/engine" "ragflow/internal/storage" + "ragflow/internal/utility" "strconv" "strings" "time" @@ -33,7 +34,6 @@ import ( "go.uber.org/zap" "gorm.io/gorm" - "github.com/google/uuid" "ragflow/internal/dao" "ragflow/internal/entity" ) @@ -154,7 +154,7 @@ func (s *ChatSessionService) SetChatSession(userID string, req *SetChatSessionRe referenceJSON, _ := json.Marshal([]interface{}{}) session := &entity.ChatSession{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DialogID: req.DialogID, Name: &name, Message: messagesJSON, @@ -356,7 +356,7 @@ func (s *ChatSessionService) CreateSession(userID, chatID string, req map[string referenceJSON, _ := json.Marshal([]interface{}{}) conv := &entity.ChatSession{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DialogID: chatID, Name: &name, Message: messagesJSON, @@ -1740,7 +1740,7 @@ func (s *ChatSessionService) normalizeCompletionMessages( if id, ok := lastUserMsg["id"].(string); ok && id != "" { messageID = id } else { - messageID = strings.ReplaceAll(uuid.New().String(), "-", "") + messageID = utility.GenerateToken() lastUserMsg["id"] = messageID for i := len(requestMessages) - 1; i >= 0; i-- { if role, _ := requestMessages[i]["role"].(string); role == "user" { @@ -1782,7 +1782,7 @@ func (s *ChatSessionService) buildDefaultCompletionDialog(tenantID string) *enti // createSessionForCompletion mirrors Python _create_session_for_completion. func (s *ChatSessionService) createSessionForCompletion(chatID string, dialog *entity.Chat, userID string) (*entity.ChatSession, error) { - newID := common.GenerateUUID() + newID := utility.GenerateUUID() name := "New session" prologue := "Hi! I'm your assistant. What can I do for you?" diff --git a/internal/service/chunk/chunk.go b/internal/service/chunk/chunk.go index bffaa865f..bdb451926 100644 --- a/internal/service/chunk/chunk.go +++ b/internal/service/chunk/chunk.go @@ -795,7 +795,7 @@ func (s *ChunkService) buildParseTasks(doc *entity.Document, bucket, objectName } tasks := make([]*entity.Task, 0, len(ranges)) for _, pageRange := range ranges { - taskID := common.GenerateUUID() + taskID := utility.GenerateUUID() progressMsg := "" digest := s.parseTaskDigest(doc, pageRange.from, pageRange.to) chunkIDs := "" diff --git a/internal/service/connector.go b/internal/service/connector.go index 5ce01161d..3baed9f26 100644 --- a/internal/service/connector.go +++ b/internal/service/connector.go @@ -30,6 +30,7 @@ import ( "net/url" "os" "ragflow/internal/engine/redis" + "ragflow/internal/utility" "strings" "time" @@ -252,7 +253,7 @@ func (s *ConnectorService) CreateConnector(userID string, req *CreateConnectorRe } connector := &entity.Connector{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), TenantID: userID, Name: req.Name, Source: req.Source, @@ -443,7 +444,7 @@ func (s *ConnectorService) StartGoogleWebOAuth(userID, source string, req *Start return nil, common.CodeServerError, err } - flowID := common.GenerateUUID() + flowID := utility.GenerateUUID() authorizationURL, err := buildGoogleAuthorizationURL(authURI, clientID, redirectURI, flowID, googleOAuthScopesForSource(source), codeChallenge) if err != nil { return nil, common.CodeServerError, fmt.Errorf("Failed to initialize Google OAuth flow. Please verify the uploaded client configuration.") @@ -1050,7 +1051,7 @@ func (s *ConnectorService) StartBoxWebOAuth(userID string, req *StartBoxWebOAuth redirectURI = defaultBoxWebOAuthRedirectURI() } - flowID := common.GenerateUUID() + flowID := utility.GenerateUUID() authorizationURL, err := buildBoxAuthorizationURL(clientID, redirectURI, flowID) if err != nil { return nil, common.CodeServerError, err diff --git a/internal/service/dataset.go b/internal/service/dataset.go index facb92845..3b08147eb 100644 --- a/internal/service/dataset.go +++ b/internal/service/dataset.go @@ -224,7 +224,7 @@ func (d *DatasetService) newRaptorOrGraphRagTask(sampleDoc *entity.Document, tas _, _ = hasher.Write([]byte{0}) } - taskID := strings.ReplaceAll(uuid.New().String(), "-", "")[:32] + taskID := utility.GenerateUUID() beginAt := time.Now().Truncate(time.Second) progressMsg := beginAt.Format("15:04:05") + " created task " + taskType @@ -735,7 +735,7 @@ func (d *DatasetService) queueDatasetDataflowTask(kb *entity.Knowledgebase, doc now := time.Now() task := &entity.Task{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DocID: doc.ID, FromPage: 0, ToPage: maximumTaskPageNumber, @@ -808,7 +808,7 @@ func (d *DatasetService) buildDatasetParseTasks(doc *entity.Document, bucket, ob digest := datasetParseTaskDigest(doc, pageRange.from, pageRange.to) chunkIDs := "" tasks = append(tasks, &entity.Task{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DocID: doc.ID, FromPage: pageRange.from, ToPage: pageRange.to, diff --git a/internal/service/deep_researcher.go b/internal/service/deep_researcher.go index e6139e170..81ae00209 100644 --- a/internal/service/deep_researcher.go +++ b/internal/service/deep_researcher.go @@ -23,6 +23,7 @@ import ( "fmt" "io" "net/http" + "ragflow/internal/utility" "regexp" "strings" "sync" @@ -35,7 +36,6 @@ import ( "ragflow/internal/service/nlp" "ragflow/internal/tokenizer" - "github.com/google/uuid" "github.com/kaptinlin/jsonrepair" "go.uber.org/zap" ) @@ -459,7 +459,7 @@ func (dr *DeepResearcher) tavilyRetrieve(ctx context.Context, query string) (map chunks := make([]map[string]interface{}, 0, len(apiResp.Results)) aggs := make([]interface{}, 0, len(apiResp.Results)) for _, r := range apiResp.Results { - id := strings.ReplaceAll(uuid.New().String(), "-", "") + id := utility.GenerateToken() chunks = append(chunks, map[string]interface{}{ "chunk_id": id, "content_ltks": tokenizeText(r.Content), diff --git a/internal/service/document.go b/internal/service/document.go index 23cc5bc2e..c68c1425e 100644 --- a/internal/service/document.go +++ b/internal/service/document.go @@ -52,7 +52,6 @@ import ( "ragflow/internal/utility" "github.com/cespare/xxhash/v2" - "github.com/google/uuid" "go.uber.org/zap" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -560,7 +559,7 @@ func (s *DocumentService) DownloadDocument(datasetID, docID string) (*DownloadDo // CreateDocument create document func (s *DocumentService) CreateDocument(req *CreateDocumentRequest) (*entity.Document, error) { document := &entity.Document{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), Name: &req.Name, KbID: req.KbID, ParserID: req.ParserID, @@ -1566,7 +1565,7 @@ func (s *DocumentService) newDocumentParseTask(doc *entity.Document, fromPage, t digest := documentParseTaskDigest(doc, fromPage, toPage) chunkIDs := "" return &entity.Task{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), DocID: doc.ID, FromPage: fromPage, ToPage: toPage, @@ -3330,7 +3329,7 @@ func (s *DocumentService) newAFileFromKB(tenantID, name, parentID string) (*enti } loc := "" folder := &entity.File{ - ID: strings.ReplaceAll(uuid.New().String(), "-", ""), + ID: utility.GenerateToken(), ParentID: parentID, TenantID: tenantID, CreatedBy: tenantID, @@ -3361,7 +3360,7 @@ func (s *DocumentService) addFileFromKB(doc *entity.Document, kbFolderID, tenant if doc.Location != nil { loc = *doc.Location } - fileID := strings.ReplaceAll(uuid.New().String(), "-", "") + fileID := utility.GenerateToken() file := &entity.File{ ID: fileID, ParentID: kbFolderID, @@ -3378,7 +3377,7 @@ func (s *DocumentService) addFileFromKB(doc *entity.Document, kbFolderID, tenant } docID := doc.ID if err := s.file2DocumentDAO.Create(&entity.File2Document{ - ID: strings.ReplaceAll(uuid.New().String(), "-", ""), + ID: utility.GenerateToken(), FileID: &fileID, DocumentID: &docID, }); err != nil { @@ -3465,7 +3464,7 @@ func normalizeWebDocumentName(name, contentType string, blob []byte) string { // newDatasetDocument builds a Document row for an upload, deriving parser_id, // suffix and content hash. blob may be nil for the empty/virtual document. func (s *DocumentService) newDatasetDocument(kb *entity.Knowledgebase, tenantID, filename, location, filetype string, parserConfig entity.JSONMap, src string, size int64, blob []byte) *entity.Document { - docID := strings.ReplaceAll(uuid.New().String(), "-", "") + docID := utility.GenerateToken() run := "0" status := "1" suffix := "" diff --git a/internal/service/file.go b/internal/service/file.go index 24dc5f70b..c0a0840a9 100644 --- a/internal/service/file.go +++ b/internal/service/file.go @@ -37,8 +37,6 @@ import ( "regexp" "strings" "time" - - "github.com/google/uuid" ) // FileService file service @@ -199,7 +197,7 @@ func (s *FileService) initSkillsFolder(rootID, tenantID string) error { } folder := &entity.File{ - ID: s.generateUUID(), + ID: utility.GenerateToken(), ParentID: rootID, TenantID: tenantID, CreatedBy: tenantID, @@ -433,7 +431,7 @@ func (s *FileService) UploadFile(tenantID, parentID string, files []*multipart.F uniqueName := s.getUniqueFilename(fileObjNames[len(fileObjNames)-1], lastFolder.ID, tenantID) fileRecord := &entity.File{ - ID: s.generateUUID(), + ID: utility.GenerateToken(), ParentID: lastFolder.ID, TenantID: tenantID, CreatedBy: tenantID, @@ -551,11 +549,6 @@ func (s *FileService) getUniqueFilename(name, parentID, tenantID string) string } } -func (s *FileService) generateUUID() string { - id := uuid.New().String() - return strings.ReplaceAll(id, "-", "") -} - // CreateFolder creates a new folder or virtual file func (s *FileService) CreateFolder(tenantID, name, parentID, fileType string) (map[string]interface{}, error) { if parentID == "" { @@ -1330,7 +1323,7 @@ func (s *FileService) checkUploadInfoHealth(userID, filename string) error { } func (s *FileService) storeUploadInfoBlob(storageImpl storage.Storage, userID, filename, contentType string, data []byte) (map[string]interface{}, error) { - location := common.GenerateUUID() + location := utility.GenerateUUID() bucket := fmt.Sprintf("%s-downloads", userID) if err := storageImpl.Put(bucket, location, data); err != nil { return nil, fmt.Errorf("failed to store file: %w", err) diff --git a/internal/service/file2document.go b/internal/service/file2document.go index c1e402221..da130c638 100644 --- a/internal/service/file2document.go +++ b/internal/service/file2document.go @@ -200,7 +200,7 @@ func (s *File2DocumentService) convertFiles(fileIDs, kbIDs []string, userID stri parserID := selectUploadParser(utility.FileType(file.Type), file.Name, kb.ParserID) suffix := strings.TrimPrefix(filepath.Ext(file.Name), ".") doc := &entity.Document{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), KbID: kb.ID, ParserID: parserID, ParserConfig: kb.ParserConfig, @@ -226,7 +226,7 @@ func (s *File2DocumentService) convertFiles(fileIDs, kbIDs []string, userID stri } mapping := &entity.File2Document{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), FileID: &fileID, DocumentID: &doc.ID, } diff --git a/internal/service/file_commit.go b/internal/service/file_commit.go index 4f38e2bc8..d2f74c555 100644 --- a/internal/service/file_commit.go +++ b/internal/service/file_commit.go @@ -25,11 +25,10 @@ import ( "ragflow/internal/dao" "ragflow/internal/entity" "ragflow/internal/storage" + "ragflow/internal/utility" "sort" - "strings" "time" - "github.com/google/uuid" "go.uber.org/zap" "gorm.io/gorm" ) @@ -65,7 +64,7 @@ func (s *FileCommitService) CreateCommit(folderID, authorID, message string, cha } // 3. Create commit record - commitID := generateCommitUUID() + commitID := utility.GenerateUUID() nowMs := time.Now().UnixMilli() commit := &entity.FileCommit{ @@ -105,7 +104,7 @@ func (s *FileCommitService) CreateCommit(folderID, authorID, message string, cha for _, change := range changes { item := &entity.FileCommitItem{ - ID: generateCommitUUID(), + ID: utility.GenerateUUID(), CommitID: commitID, FileID: change.FileID, Operation: change.Operation, @@ -629,9 +628,3 @@ func computeLiveFileHash(folderID, fileID string, file *entity.File) string { hash := sha256.Sum256(data) return hex.EncodeToString(hash[:]) } - -// generateCommitUUID generates a UUID without dashes -func generateCommitUUID() string { - id := uuid.New().String() - return strings.ReplaceAll(id, "-", "") -} diff --git a/internal/service/mcp.go b/internal/service/mcp.go index fa5f6752f..24e7b337a 100644 --- a/internal/service/mcp.go +++ b/internal/service/mcp.go @@ -154,7 +154,7 @@ func (s *MCPService) CreateMCPServer(tenantID string, req CreateMCPServerRequest variables["tools"] = tools server := &entity.MCPServer{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), Name: req.Name, TenantID: tenantID, URL: req.URL, @@ -643,7 +643,7 @@ func (s *MCPService) ImportServers(tenantID string, servers map[string]map[strin variables["tools"] = toolsAsMap(tools) server := &entity.MCPServer{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), TenantID: tenantID, Name: newName, URL: url, diff --git a/internal/service/memory.go b/internal/service/memory.go index 039427da0..e1f59aaee 100644 --- a/internal/service/memory.go +++ b/internal/service/memory.go @@ -24,6 +24,7 @@ import ( "ragflow/internal/common" "ragflow/internal/entity" models "ragflow/internal/entity/models" + "ragflow/internal/utility" "strconv" "strings" "time" @@ -396,7 +397,7 @@ func (s *MemoryService) CreateMemory(tenantID string, req *CreateMemoryRequest) memoryTypeInt := dao.CalculateMemoryType(uniqueMemoryTypes) systemPrompt := PromptAssembler{}.AssembleSystemPrompt(uniqueMemoryTypes) - newID := common.GenerateUUID() + newID := utility.GenerateUUID() memory := &entity.Memory{ ID: newID, diff --git a/internal/service/memory_message_service.go b/internal/service/memory_message_service.go index e7e82ed4d..7398eb60a 100644 --- a/internal/service/memory_message_service.go +++ b/internal/service/memory_message_service.go @@ -56,9 +56,9 @@ import ( "context" "errors" "fmt" + "ragflow/internal/utility" "time" - "ragflow/internal/common" "ragflow/internal/dao" redisengine "ragflow/internal/engine/redis" "ragflow/internal/entity" @@ -316,7 +316,7 @@ func (s *MemoryMessageService) insertTask(_ context.Context, row map[string]any) // generator later without changing call sites. Avoids an // import-cycle with internal/uuid at the package boundary. func newUUIDString() string { - return common.GenerateUUID() + return utility.GenerateUUID() } func taskFromRow(row map[string]any) *entity.Task { diff --git a/internal/service/search.go b/internal/service/search.go index 0b016f73c..cbfa72c02 100644 --- a/internal/service/search.go +++ b/internal/service/search.go @@ -22,6 +22,7 @@ import ( "ragflow/internal/common" "ragflow/internal/dao" "ragflow/internal/entity" + "ragflow/internal/utility" "strings" "gorm.io/gorm" @@ -209,7 +210,7 @@ type CreateSearchResponse struct { // 7. Return {search_id: id} on success func (s *SearchService) CreateSearch(userID string, name string, description *string) (*CreateSearchResponse, error) { // Generate UUID for search ID (same as Python get_uuid()) - searchID := common.GenerateUUID() + searchID := utility.GenerateUUID() // Generate unique name (same as Python duplicate_name) uniqueName, err := common.DuplicateName(func(name string, tid string) bool { diff --git a/internal/service/skill_search.go b/internal/service/skill_search.go index c6c86097a..ca763b8a5 100644 --- a/internal/service/skill_search.go +++ b/internal/service/skill_search.go @@ -31,7 +31,6 @@ import ( "ragflow/internal/utility" "strings" - "github.com/google/uuid" "go.uber.org/zap" ) @@ -744,11 +743,6 @@ func sortResults(results []entity.SkillSearchResult) { } } -// GenerateID generates a unique ID -func generateID() string { - return strings.ReplaceAll(uuid.New().String(), "-", "")[:32] -} - // CalculateContentHash calculates SHA256 hash of skill content func CalculateContentHash(name, description string, tags []string, content string) string { h := sha256.New() diff --git a/internal/service/skill_space.go b/internal/service/skill_space.go index 3610bcdd6..f25446941 100644 --- a/internal/service/skill_space.go +++ b/internal/service/skill_space.go @@ -23,11 +23,10 @@ import ( "ragflow/internal/dao" "ragflow/internal/engine" "ragflow/internal/entity" - "strings" + "ragflow/internal/utility" "sync" "time" - "github.com/google/uuid" "go.uber.org/zap" ) @@ -122,7 +121,7 @@ func (s *SkillSpaceService) getSkillsFolderID(tenantID string) (string, error) { // Skills folder not found, create it common.Info("Creating skills folder", zap.String("tenant_id", tenantID)) - folderID := generateSpaceID() + folderID := utility.GenerateUUID() folder := &entity.File{ ID: folderID, ParentID: rootFolder.ID, @@ -205,8 +204,8 @@ func (s *SkillSpaceService) CreateSpace(req *CreateSpaceRequest) (map[string]int } // Generate space ID and folder ID - spaceID := generateSpaceID() - folderID := generateSpaceID() + spaceID := utility.GenerateUUID() + folderID := utility.GenerateUUID() // Create folder for the space under skills folder folder := &entity.File{ @@ -545,8 +544,3 @@ func (s *SkillSpaceService) GetSpaceByFolderID(folderID, tenantID string) (map[s return space.ToMap(), common.CodeSuccess, nil } - -// generateSpaceID generates a unique ID for space -func generateSpaceID() string { - return strings.ReplaceAll(uuid.New().String(), "-", "")[:32] -} diff --git a/internal/service/tenant.go b/internal/service/tenant.go index 9befb6b73..3744ad1fd 100644 --- a/internal/service/tenant.go +++ b/internal/service/tenant.go @@ -23,6 +23,7 @@ import ( "ragflow/internal/dao" "ragflow/internal/engine" "ragflow/internal/entity" + "ragflow/internal/utility" "strings" ) @@ -835,14 +836,14 @@ func (s *TenantService) AddMember(userID, tenantID string, req *AddMemberRequest status := "1" ut := &entity.UserTenant{ - ID: common.GenerateUUID(), + ID: utility.GenerateUUID(), UserID: invitee.ID, TenantID: tenantID, Role: TenantRoleInvite, InvitedBy: userID, Status: &status, } - if err := s.userTenantDAO.Create(ut); err != nil { + if err = s.userTenantDAO.Create(ut); err != nil { return nil, common.CodeServerError, fmt.Errorf("failed to create invitation: %w", err) } diff --git a/internal/syncer/syncer.go b/internal/syncer/syncer.go index 26a11fed8..6df9e539b 100644 --- a/internal/syncer/syncer.go +++ b/internal/syncer/syncer.go @@ -22,6 +22,7 @@ import ( "ragflow/internal/common" "ragflow/internal/dao" "ragflow/internal/entity" + "ragflow/internal/utility" "sync" "time" @@ -48,7 +49,7 @@ type Syncer struct { func NewSyncer(maxConcurrency int, pollInterval time.Duration) *Syncer { ctx, cancel := context.WithCancel(context.Background()) return &Syncer{ - id: common.GenerateUUID(), + id: utility.GenerateUUID(), maxConcurrency: maxConcurrency, pollInterval: pollInterval, ctx: ctx, diff --git a/internal/utility/token.go b/internal/utility/token.go index 34cc227ea..7807fb316 100644 --- a/internal/utility/token.go +++ b/internal/utility/token.go @@ -142,9 +142,16 @@ func GenerateToken() string { return strings.ReplaceAll(uuid.New().String(), "-", "") } -// GenerateAPIToken generates a secure random access key -// Equivalent to Python's generate_confirmation_token(): -// return "ragflow-" + secrets.token_urlsafe(32) +// GenerateUUID generates a UUID without dashes +func GenerateUUID() string { + newID := strings.ReplaceAll(uuid.New().String(), "-", "") + if len(newID) > 32 { + newID = newID[:32] + } + return newID +} + +// GenerateAPIToken generates secure random access key func GenerateAPIToken() string { // Generate 32 random bytes bytes := make([]byte, 32) @@ -152,18 +159,11 @@ func GenerateAPIToken() string { // Fallback to UUID if random generation fails return "ragflow-" + strings.ReplaceAll(uuid.New().String(), "-", "") } - // Use URL-safe base64 encoding (same as Python's token_urlsafe) + // Use URL-safe base64 encoding return "ragflow-" + base64.RawURLEncoding.EncodeToString(bytes) } // GenerateBetaAPIToken generates a beta access key -// Equivalent to Python's: generate_confirmation_token().replace("ragflow-", "")[:32] -func GenerateBetaAPIToken(accessKey string) string { - // Remove "ragflow-" prefix - withoutPrefix := strings.TrimPrefix(accessKey, "ragflow-") - // Take first 32 characters - if len(withoutPrefix) > 32 { - return withoutPrefix[:32] - } - return withoutPrefix +func GenerateBetaAPIToken() string { + return GenerateUUID() }