thread-master/backend/internal/library/personacopy/rewrite_draft.go

140 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package personacopy
import (
"context"
"fmt"
"strings"
"time"
libformula "haixun-backend/internal/library/formula"
"haixun-backend/internal/library/style8d"
domai "haixun-backend/internal/model/ai/domain/usecase"
aiusecase "haixun-backend/internal/model/ai/usecase"
cfentity "haixun-backend/internal/model/content_formula/domain/entity"
contentformuladomain "haixun-backend/internal/model/content_formula/domain/usecase"
copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase"
personadomain "haixun-backend/internal/model/persona/domain/usecase"
placementusecase "haixun-backend/internal/model/placement/usecase"
threadsaccountdomain "haixun-backend/internal/model/threads_account/domain/usecase"
)
type RewriteDraftInput struct {
TenantID string
OwnerUID string
PersonaID string
AccountID string
ReferenceText string
Topic string
Brief string
SaveLabel string
UseWebSearch bool
DraftCount int
}
type RewriteDraftDeps struct {
Persona personadomain.UseCase
ContentFormula contentformuladomain.UseCase
CopyDraft copydraftdomain.UseCase
ThreadsAccount threadsaccountdomain.UseCase
Placement placementusecase.UseCase
AI domai.UseCase
}
func RunRewriteDraft(ctx context.Context, deps RewriteDraftDeps, in RewriteDraftInput, progress ProgressFn) (int, error) {
if progress == nil {
progress = func(string, int) {}
}
referenceText := strings.TrimSpace(in.ReferenceText)
topic := strings.TrimSpace(in.Topic)
if referenceText == "" {
return 0, fmt.Errorf("reference_text is required")
}
if topic == "" {
return 0, fmt.Errorf("topic is required")
}
progress("讀取人設…", 5)
persona, err := deps.Persona.Get(ctx, in.TenantID, in.OwnerUID, in.PersonaID)
if err != nil {
return 0, err
}
if !style8d.HasReady8D(persona.Persona, persona.StyleProfile) {
return 0, fmt.Errorf("請先完成人設 8D 對標分析")
}
credential, err := deps.ThreadsAccount.ResolveMemberAiCredential(ctx, in.TenantID, in.OwnerUID)
if err != nil {
return 0, err
}
providerID, err := aiusecase.MapWorkerProvider(credential.Provider)
if err != nil {
return 0, err
}
aiReq := domai.GenerateRequest{
Provider: providerID,
Model: credential.Model,
Credential: domai.Credential{APIKey: credential.APIKey},
}
personaBlock := style8d.ResolvePersonaBlock(persona.Persona, persona.StyleProfile, persona.Brief)
progress(fmt.Sprintf("分析參考貼文寫法(%s / %s…", credential.Provider, credential.Model), 15)
analysis, err := libformula.AnalyzePasted(ctx, deps.AI, aiReq, libformula.AnalyzePastedInput{
PostText: referenceText,
PersonaBlock: personaBlock,
})
if err != nil {
return 0, fmt.Errorf("分析參考貼文失敗:%w", err)
}
if analysis == nil {
return 0, fmt.Errorf("分析未產出有效寫法公式")
}
label := strings.TrimSpace(in.SaveLabel)
if label == "" {
label = fmt.Sprintf("貼文改寫 %s", time.Now().UTC().Format("2006-01-02"))
}
progress("存入寫法公式…", 30)
saved, err := deps.ContentFormula.Create(ctx, contentformuladomain.CreateRequest{
TenantID: in.TenantID,
OwnerUID: in.OwnerUID,
AccountID: in.AccountID,
Label: label,
SourceType: cfentity.SourcePaste,
SourceRef: "paste",
SourcePostText: referenceText,
Summary: analysis.Summary,
Wins: analysis.Wins,
Improvements: analysis.Improvements,
Formula: analysis.Formula,
PostTemplate: analysis.PostTemplate,
HookPattern: analysis.HookPattern,
Structure: analysis.Structure,
ReplicationTips: analysis.ReplicationTips,
Avoid: analysis.Avoid,
})
if err != nil {
return 0, err
}
return RunFormulaDraft(ctx, FormulaDraftDeps{
Persona: deps.Persona,
ContentFormula: deps.ContentFormula,
CopyDraft: deps.CopyDraft,
ThreadsAccount: deps.ThreadsAccount,
Placement: deps.Placement,
AI: deps.AI,
}, FormulaDraftInput{
TenantID: in.TenantID,
OwnerUID: in.OwnerUID,
PersonaID: in.PersonaID,
AccountID: in.AccountID,
FormulaID: saved.ID,
Topic: topic,
Brief: in.Brief,
UseWebSearch: in.UseWebSearch,
DraftCount: in.DraftCount,
}, func(summary string, percentage int) {
adjusted := 35 + (percentage * 65 / 100)
progress(summary, adjusted)
})
}