This commit is contained in:
@@ -36,6 +36,7 @@ type extractionSnapshot struct {
|
||||
tenantID, subjectID, status string
|
||||
storyExtractionAllowed bool
|
||||
turns []turn
|
||||
maxSequence int64
|
||||
digest string
|
||||
}
|
||||
|
||||
@@ -84,6 +85,10 @@ func (p *Processor) Handle(ctx context.Context, event outbox.Event) error {
|
||||
if !snapshot.storyExtractionAllowed {
|
||||
return nil
|
||||
}
|
||||
generationVersion := requestedGenerationVersion(event.Payload)
|
||||
if generationVersion < snapshot.maxSequence {
|
||||
return nil
|
||||
}
|
||||
sourceTurns := subjectTurns(snapshot.turns)
|
||||
if len(sourceTurns) == 0 {
|
||||
return outbox.Retryable(ErrConversationContentNotReady)
|
||||
@@ -94,14 +99,6 @@ func (p *Processor) Handle(ctx context.Context, event outbox.Event) error {
|
||||
return err
|
||||
}
|
||||
|
||||
generationVersion := int64(1)
|
||||
var payload struct {
|
||||
GenerationVersion int64 `json:"generation_version"`
|
||||
}
|
||||
if json.Unmarshal(event.Payload, &payload) == nil && payload.GenerationVersion > 0 {
|
||||
generationVersion = payload.GenerationVersion
|
||||
}
|
||||
|
||||
// The model call above is deliberately outside a database transaction. The
|
||||
// conversation row is locked only for the short revalidation and write phase.
|
||||
tx, err := p.pool.BeginTx(ctx, pgx.TxOptions{})
|
||||
@@ -151,7 +148,7 @@ func (p *Processor) generateSafely(ctx context.Context, content string) (Generat
|
||||
}
|
||||
|
||||
func generatedSafetyContent(result GenerationResult) string {
|
||||
return strings.Join([]string{result.Summary, result.OpenTopic, result.StoryTitle, result.StoryContent, result.FactContent}, "\n")
|
||||
return strings.Join([]string{result.Summary, strings.Join(result.Keywords, "、"), result.OpenTopic, result.StoryTitle, result.StoryContent, result.FactContent}, "\n")
|
||||
}
|
||||
|
||||
func loadExtractionSnapshot(ctx context.Context, q queryer, conversationID string, lock bool) (extractionSnapshot, error) {
|
||||
@@ -179,7 +176,7 @@ func loadExtractionSnapshot(ctx context.Context, q queryer, conversationID strin
|
||||
}
|
||||
snapshot.storyExtractionAllowed = consents["story_extraction"]
|
||||
rows, err := q.Query(ctx, `
|
||||
SELECT id::text,public_id::text,speaker,final_text,interrupted
|
||||
SELECT id::text,public_id::text,speaker,final_text,interrupted,sequence_no
|
||||
FROM conversation_turn WHERE conversation_id=$1::uuid ORDER BY sequence_no,id`, conversationID)
|
||||
if err != nil {
|
||||
return extractionSnapshot{}, fmt.Errorf("read extraction turns: %w", err)
|
||||
@@ -187,9 +184,13 @@ func loadExtractionSnapshot(ctx context.Context, q queryer, conversationID strin
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var item turn
|
||||
if err = rows.Scan(&item.id, &item.publicID, &item.speaker, &item.text, &item.interrupted); err != nil {
|
||||
var sequence int64
|
||||
if err = rows.Scan(&item.id, &item.publicID, &item.speaker, &item.text, &item.interrupted, &sequence); err != nil {
|
||||
return extractionSnapshot{}, err
|
||||
}
|
||||
if sequence > snapshot.maxSequence {
|
||||
snapshot.maxSequence = sequence
|
||||
}
|
||||
snapshot.turns = append(snapshot.turns, item)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
@@ -199,6 +200,16 @@ func loadExtractionSnapshot(ctx context.Context, q queryer, conversationID strin
|
||||
return snapshot, nil
|
||||
}
|
||||
|
||||
func requestedGenerationVersion(payload json.RawMessage) int64 {
|
||||
var value struct {
|
||||
GenerationVersion int64 `json:"generation_version"`
|
||||
}
|
||||
if json.Unmarshal(payload, &value) == nil && value.GenerationVersion > 0 {
|
||||
return value.GenerationVersion
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func snapshotDigest(snapshot extractionSnapshot) string {
|
||||
type digestTurn struct {
|
||||
ID string `json:"id"`
|
||||
@@ -250,7 +261,7 @@ func storeGeneration(ctx context.Context, tx pgx.Tx, conversationID string, snap
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO conversation_summary (tenant_id,subject_id,conversation_id,summary_type,content,source_turn_ids,model_ref,prompt_version,generation_version,confidence,status)
|
||||
VALUES ($1::uuid,$2::uuid,$3::uuid,'conversation_summary',$4,$5::jsonb,$6,$7,$8,$9,'READY')
|
||||
ON CONFLICT (conversation_id,summary_type,generation_version) DO NOTHING`, snapshot.tenantID, snapshot.subjectID, conversationID, generated.Summary, sourceJSON, generated.ModelRef, generated.PromptVersion, generationVersion, generated.Confidence); err != nil {
|
||||
ON CONFLICT (conversation_id,summary_type,generation_version) DO NOTHING`, snapshot.tenantID, snapshot.subjectID, conversationID, summaryWithKeywords(generated.Summary, generated.Keywords), sourceJSON, generated.ModelRef, generated.PromptVersion, generationVersion, generated.Confidence); err != nil {
|
||||
return fmt.Errorf("store conversation summary: %w", err)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
@@ -299,6 +310,14 @@ func storeGeneration(ctx context.Context, tx pgx.Tx, conversationID string, snap
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
func summaryWithKeywords(summary string, keywords []string) string {
|
||||
keywords = normalizedKeywords(keywords)
|
||||
if len(keywords) == 0 {
|
||||
return summary
|
||||
}
|
||||
return summary + "\n关键词:" + strings.Join(keywords, "、")
|
||||
}
|
||||
|
||||
func truncateRunes(value string, limit int) string {
|
||||
characters := []rune(value)
|
||||
if len(characters) <= limit {
|
||||
|
||||
Reference in New Issue
Block a user