Refactor brand service and related components
- Removed ListQuestionVersions method and associated types from BrandService and Queries. - Updated PromptRuleGenerationService to change task naming and handling. - Enhanced ScheduleTaskService to support filtering by created date range and keyword. - Introduced InstantTaskService for managing instant tasks with appropriate filtering and response structures. - Added InstantTaskHandler for handling API requests related to instant tasks. - Created InstantTaskTab component for the admin web interface to display and manage instant tasks. - Updated database migrations to rename source types for articles and generation tasks. - Adjusted models and repository queries to reflect the removal of question version handling.
This commit is contained in:
@@ -62,6 +62,8 @@ type promptRuleGenerationRecord struct {
|
||||
Status string
|
||||
}
|
||||
|
||||
const promptRuleGeneratingTitlePlaceholder = "标题生成中"
|
||||
|
||||
func NewPromptRuleGenerationService(
|
||||
pool *pgxpool.Pool,
|
||||
llmClient llm.Client,
|
||||
@@ -121,12 +123,12 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
return nil, response.ErrBadRequest(40018, "generate_count_not_supported", "prompt rule instant generation currently supports generate_count = 1 only")
|
||||
}
|
||||
|
||||
initialTitle := strings.TrimSpace(extractString(extra, "task_name"))
|
||||
if initialTitle == "" {
|
||||
initialTitle = strings.TrimSpace(rule.Name)
|
||||
taskName := strings.TrimSpace(extractString(extra, "task_name"))
|
||||
if taskName == "" {
|
||||
taskName = strings.TrimSpace(rule.Name)
|
||||
}
|
||||
if initialTitle == "" {
|
||||
initialTitle = "Generated Article"
|
||||
if taskName == "" {
|
||||
taskName = "即时任务"
|
||||
}
|
||||
|
||||
quotaRepo := repository.NewQuotaRepository(s.pool)
|
||||
@@ -136,11 +138,14 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
}
|
||||
|
||||
inputParams := map[string]interface{}{
|
||||
"title": initialTitle,
|
||||
"prompt_rule_id": req.PromptRuleID,
|
||||
"task_name": taskName,
|
||||
"target_platform": strings.TrimSpace(derefString(req.TargetPlatform)),
|
||||
"enable_web_search": extractBool(extra, "enable_web_search"),
|
||||
}
|
||||
if generationMode := strings.TrimSpace(extractString(extra, "generation_mode")); generationMode != "" {
|
||||
inputParams["generation_mode"] = generationMode
|
||||
}
|
||||
platformIDs := parsePlatformIDs(derefString(req.TargetPlatform))
|
||||
if len(platformIDs) > 0 {
|
||||
inputParams["target_platforms"] = platformIDs
|
||||
@@ -150,7 +155,7 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
}
|
||||
|
||||
inputJSON, _ := json.Marshal(inputParams)
|
||||
wizardStateJSON, _ := mergeArticleWizardState(nil, initialTitle, platformIDs)
|
||||
wizardStateJSON, _ := mergeArticleWizardState(nil, promptRuleGeneratingTitlePlaceholder, platformIDs)
|
||||
|
||||
tx, err := s.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
@@ -195,7 +200,7 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
var articleID int64
|
||||
err = tx.QueryRow(ctx, `
|
||||
INSERT INTO articles (tenant_id, source_type, prompt_rule_id, generate_status, publish_status, wizard_state_json)
|
||||
VALUES ($1, 'prompt_rule', $2, 'generating', 'unpublished', $3)
|
||||
VALUES ($1, 'custom_generation', $2, 'generating', 'unpublished', $3)
|
||||
RETURNING id
|
||||
`, actor.TenantID, req.PromptRuleID, wizardStateJSON).Scan(&articleID)
|
||||
if err != nil {
|
||||
@@ -211,7 +216,7 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
TenantID: actor.TenantID,
|
||||
ArticleID: &articleID,
|
||||
QuotaReservationID: &reservationID,
|
||||
TaskType: "prompt_rule",
|
||||
TaskType: "custom_generation",
|
||||
InputParamsJSON: inputJSON,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -230,7 +235,7 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
ReservationID: reservationID,
|
||||
Prompt: buildPromptRuleGenerationPrompt(rule, inputParams),
|
||||
InputParams: inputParams,
|
||||
InitialTitle: initialTitle,
|
||||
InitialTitle: promptRuleGeneratingTitlePlaceholder,
|
||||
WebSearch: llm.WebSearchOptions{
|
||||
Enabled: extractBool(extra, "enable_web_search"),
|
||||
},
|
||||
@@ -242,7 +247,7 @@ func (s *PromptRuleGenerationService) GenerateFromRule(ctx context.Context, req
|
||||
}
|
||||
|
||||
if s.streamEnabled {
|
||||
s.streams.Start(articleID, taskID, initialTitle)
|
||||
s.streams.Start(articleID, taskID, promptRuleGeneratingTitlePlaceholder)
|
||||
}
|
||||
|
||||
return &GenerateFromRuleResponse{ArticleID: articleID, TaskID: taskID}, nil
|
||||
@@ -392,6 +397,10 @@ func (s *PromptRuleGenerationService) executeGeneration(ctx context.Context, job
|
||||
func (s *PromptRuleGenerationService) failGeneration(ctx context.Context, job promptRuleGenerationJob, title, stage string, genErr error) {
|
||||
errMsg := formatGenerationFailure(stage, genErr)
|
||||
now := time.Now()
|
||||
failureTitle := strings.TrimSpace(extractString(job.InputParams, "task_name"))
|
||||
if failureTitle == "" {
|
||||
failureTitle = title
|
||||
}
|
||||
|
||||
auditRepo := repository.NewAuditRepository(s.pool)
|
||||
articleRepo := repository.NewArticleRepository(s.pool)
|
||||
@@ -405,6 +414,14 @@ func (s *PromptRuleGenerationService) failGeneration(ctx context.Context, job pr
|
||||
CompletedAt: &now,
|
||||
})
|
||||
_ = articleRepo.UpdateArticleGenerateStatus(ctx, job.ArticleID, job.TenantID, "failed")
|
||||
if failureTitle != "" {
|
||||
_, _ = s.pool.Exec(ctx, `
|
||||
UPDATE articles
|
||||
SET wizard_state_json = jsonb_set(COALESCE(wizard_state_json, '{}'::jsonb), '{title}', to_jsonb($1::text), true),
|
||||
updated_at = NOW()
|
||||
WHERE id = $2 AND tenant_id = $3
|
||||
`, failureTitle, job.ArticleID, job.TenantID)
|
||||
}
|
||||
|
||||
balance, balanceErr := quotaRepo.GetCurrentBalance(ctx, job.TenantID, "article_generation")
|
||||
if balanceErr == nil {
|
||||
@@ -426,7 +443,7 @@ func (s *PromptRuleGenerationService) failGeneration(ctx context.Context, job pr
|
||||
_ = quotaRepo.RefundReservation(ctx, job.ReservationID, job.TenantID)
|
||||
|
||||
if s.streamEnabled {
|
||||
s.streams.Fail(job.ArticleID, job.TaskID, title, errMsg)
|
||||
s.streams.Fail(job.ArticleID, job.TaskID, failureTitle, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,8 +451,8 @@ func buildPromptRuleGenerationPrompt(rule *promptRuleGenerationRecord, params ma
|
||||
sections := []string{strings.TrimSpace(rule.PromptContent)}
|
||||
|
||||
var supplements []string
|
||||
if title := strings.TrimSpace(extractString(params, "title")); title != "" {
|
||||
supplements = append(supplements, "任务名称:"+title)
|
||||
if taskName := strings.TrimSpace(extractString(params, "task_name")); taskName != "" {
|
||||
supplements = append(supplements, "任务名称:"+taskName)
|
||||
}
|
||||
if rule.Scene != nil && strings.TrimSpace(*rule.Scene) != "" {
|
||||
supplements = append(supplements, "适用场景:"+strings.TrimSpace(*rule.Scene))
|
||||
@@ -454,7 +471,7 @@ func buildPromptRuleGenerationPrompt(rule *promptRuleGenerationRecord, params ma
|
||||
sections = append(sections, "补充要求:\n- "+strings.Join(supplements, "\n- "))
|
||||
}
|
||||
|
||||
sections = append(sections, "输出要求:\n1. 直接输出完整可发布的中文 Markdown 文章。\n2. 标题使用一级标题。\n3. 不要输出你的思考过程、解释或致歉。")
|
||||
sections = append(sections, "输出要求:\n1. 直接输出完整可发布的中文 Markdown 文章。\n2. 标题使用一级标题,并由 AI 根据正文内容自行生成,不要直接复用任务名称。\n3. 不要输出你的思考过程、解释或致歉。")
|
||||
return strings.Join(sections, "\n\n")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user