87 lines
4.0 KiB
Go
87 lines
4.0 KiB
Go
package opsconfig
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"data-terminal-cloud/internal/identity"
|
|
)
|
|
|
|
type ContentQualitySummary struct {
|
|
ModelRef string `json:"model_ref"`
|
|
PromptVersion string `json:"prompt_version"`
|
|
StoryCandidates int64 `json:"story_candidates"`
|
|
FactCandidates int64 `json:"fact_candidates"`
|
|
Confirmed int64 `json:"confirmed"`
|
|
Edited int64 `json:"edited"`
|
|
Rejected int64 `json:"rejected"`
|
|
Disabled int64 `json:"disabled"`
|
|
ErrorTypes map[string]int64 `json:"error_types"`
|
|
}
|
|
|
|
func (s *Service) ContentQuality(ctx context.Context, principal identity.Principal, tenantPublicID, modelRef, promptVersion string) ([]ContentQualitySummary, error) {
|
|
currentActor, err := s.resolveActor(ctx, principal, tenantPublicID, "ops_viewer", "ops_operator", "ops_approver", "ops_admin")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
modelRef = strings.TrimSpace(modelRef)
|
|
promptVersion = strings.TrimSpace(promptVersion)
|
|
rows, err := s.pool.Query(ctx, `
|
|
WITH generated AS (
|
|
SELECT COALESCE(sr.model_ref,'unknown') model_ref,COALESCE(sr.prompt_version,'unknown') prompt_version,
|
|
count(DISTINCT sd.id) story_candidates,count(DISTINCT fc.id) fact_candidates
|
|
FROM story_draft sd JOIN story_revision sr ON sr.story_id=sd.id AND sr.revision_no=1
|
|
LEFT JOIN fact_candidate fc ON fc.story_id=sd.id
|
|
WHERE sd.tenant_id=$1::uuid AND (NULLIF($2,'') IS NULL OR sr.model_ref=$2) AND (NULLIF($3,'') IS NULL OR sr.prompt_version=$3)
|
|
GROUP BY COALESCE(sr.model_ref,'unknown'),COALESCE(sr.prompt_version,'unknown')
|
|
), signals AS (
|
|
SELECT COALESCE(model_ref,'unknown') model_ref,COALESCE(prompt_version,'unknown') prompt_version,
|
|
count(*) FILTER(WHERE action='CONFIRMED') confirmed,count(*) FILTER(WHERE action='EDITED') edited,
|
|
count(*) FILTER(WHERE action='REJECTED') rejected,count(*) FILTER(WHERE action='DISABLED') disabled
|
|
FROM content_review_signal WHERE tenant_id=$1::uuid
|
|
AND (NULLIF($2,'') IS NULL OR model_ref=$2) AND (NULLIF($3,'') IS NULL OR prompt_version=$3)
|
|
GROUP BY COALESCE(model_ref,'unknown'),COALESCE(prompt_version,'unknown')
|
|
)
|
|
SELECT COALESCE(g.model_ref,s.model_ref),COALESCE(g.prompt_version,s.prompt_version),
|
|
COALESCE(g.story_candidates,0),COALESCE(g.fact_candidates,0),COALESCE(s.confirmed,0),COALESCE(s.edited,0),COALESCE(s.rejected,0),COALESCE(s.disabled,0)
|
|
FROM generated g FULL JOIN signals s USING(model_ref,prompt_version)
|
|
ORDER BY COALESCE(g.model_ref,s.model_ref),COALESCE(g.prompt_version,s.prompt_version)`, currentActor.tenantID, modelRef, promptVersion)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query content quality summary: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
items := make([]ContentQualitySummary, 0)
|
|
lookup := make(map[string]int)
|
|
for rows.Next() {
|
|
var item ContentQualitySummary
|
|
item.ErrorTypes = map[string]int64{}
|
|
if err := rows.Scan(&item.ModelRef, &item.PromptVersion, &item.StoryCandidates, &item.FactCandidates, &item.Confirmed, &item.Edited, &item.Rejected, &item.Disabled); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, item)
|
|
lookup[item.ModelRef+"\x00"+item.PromptVersion] = len(items) - 1
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
errorRows, err := s.pool.Query(ctx, `SELECT COALESCE(model_ref,'unknown'),COALESCE(prompt_version,'unknown'),error_type,count(*) FROM content_review_signal
|
|
WHERE tenant_id=$1::uuid AND error_type IS NOT NULL AND (NULLIF($2,'') IS NULL OR model_ref=$2) AND (NULLIF($3,'') IS NULL OR prompt_version=$3)
|
|
GROUP BY COALESCE(model_ref,'unknown'),COALESCE(prompt_version,'unknown'),error_type`, currentActor.tenantID, modelRef, promptVersion)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer errorRows.Close()
|
|
for errorRows.Next() {
|
|
var model, prompt, errorType string
|
|
var count int64
|
|
if err := errorRows.Scan(&model, &prompt, &errorType, &count); err != nil {
|
|
return nil, err
|
|
}
|
|
if index, ok := lookup[model+"\x00"+prompt]; ok {
|
|
items[index].ErrorTypes[errorType] = count
|
|
}
|
|
}
|
|
return items, errorRows.Err()
|
|
}
|