Move LLM validators to PromptKit prompt variables
This commit is contained in:
@@ -17,13 +17,9 @@ import (
|
||||
"gitea.maximumdirect.net/eric/audita/internal/prompts"
|
||||
)
|
||||
|
||||
type LLMPromptBuilder func(validationPayload []LLMValidationItem, transcriptDescription string) ([]LLMMessage, error)
|
||||
|
||||
type LLMBackedValidator struct {
|
||||
name string
|
||||
validatorType LLMValidatorType
|
||||
promptBuilder LLMPromptBuilder
|
||||
model string
|
||||
estimator chunking.TokenEstimator
|
||||
}
|
||||
|
||||
@@ -39,10 +35,9 @@ func (v *LLMBackedValidator) SetTokenEstimator(estimator chunking.TokenEstimator
|
||||
v.estimator = estimator
|
||||
}
|
||||
|
||||
func NewLLMBackedValidator(name string, validatorType LLMValidatorType, model string) (*LLMBackedValidator, error) {
|
||||
builder, err := promptBuilderForType(validatorType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func NewLLMBackedValidator(name string, validatorType LLMValidatorType) (*LLMBackedValidator, error) {
|
||||
if validatorPromptMetadata(validatorType).PromptID == "" {
|
||||
return nil, fmt.Errorf("unsupported LLM validator type %q", validatorType)
|
||||
}
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return nil, fmt.Errorf("validator name must not be empty")
|
||||
@@ -50,8 +45,6 @@ func NewLLMBackedValidator(name string, validatorType LLMValidatorType, model st
|
||||
return &LLMBackedValidator{
|
||||
name: name,
|
||||
validatorType: validatorType,
|
||||
promptBuilder: builder,
|
||||
model: strings.TrimSpace(model),
|
||||
estimator: chunking.NewSimpleTokenEstimator(),
|
||||
}, nil
|
||||
}
|
||||
@@ -77,8 +70,8 @@ func (v *LLMBackedValidator) Validate(ctx context.Context, req Request) (Result,
|
||||
}
|
||||
|
||||
maxTokens := config.DefaultValidationMaxPromptTokens
|
||||
if req.Config != nil && req.Config.ValidationMaxPromptTokens > 0 {
|
||||
maxTokens = req.Config.ValidationMaxPromptTokens
|
||||
if req.Config != nil && req.Config.Validation.MaxPromptTokens > 0 {
|
||||
maxTokens = req.Config.Validation.MaxPromptTokens
|
||||
}
|
||||
|
||||
warnings := append([]stagewarnings.StageWarning(nil), oversizedValidationWarnings(v.name, maxTokens, validationReq.Items, v.estimator)...)
|
||||
@@ -103,22 +96,23 @@ func (v *LLMBackedValidator) Validate(ctx context.Context, req Request) (Result,
|
||||
for _, batch := range batches {
|
||||
transcriptDescription := ""
|
||||
if req.Config != nil {
|
||||
transcriptDescription = req.Config.TranscriptDescription
|
||||
transcriptDescription = req.Config.Context.Description
|
||||
}
|
||||
messages, err := v.promptBuilder(batch.Items, transcriptDescription)
|
||||
variables, err := BuildValidationVariables(batch.Items, transcriptDescription)
|
||||
if err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
|
||||
var response LLMValidationResponse
|
||||
var completion StructuredCompletionResponse
|
||||
responseSchema := responseschema.MustLookup(responseschema.ValidatorDecisionSetKey)
|
||||
promptMetadata := validatorPromptMetadata(v.validatorType)
|
||||
stage := stagename.ValidatorBatch(req.ModuleInstance, v.name, batch.BatchIndex)
|
||||
call := func(callCtx context.Context) error {
|
||||
_, err = req.LLMClient.CompleteStructured(callCtx, StructuredCompletionRequest{
|
||||
StageName: stage,
|
||||
Messages: messages,
|
||||
Model: resolvedValidationModel(req.Config, v.model),
|
||||
ResponseSchema: &responseSchema,
|
||||
completion, err = req.LLMClient.CompleteStructured(callCtx, StructuredCompletionRequest{
|
||||
PromptID: promptMetadata.PromptID, PromptVersion: promptMetadata.PromptVersion,
|
||||
Variables: variables, Schema: responseschema.ValidatorDecisionSetKey,
|
||||
Context: structuredoutput.DiagnosticContext{Role: "validation", ModuleKey: req.ModuleKey, ModuleInstance: req.ModuleInstance, BatchIndex: &batch.BatchIndex, ValidatorName: v.name},
|
||||
}, &response)
|
||||
return err
|
||||
}
|
||||
@@ -129,18 +123,17 @@ func (v *LLMBackedValidator) Validate(ctx context.Context, req Request) (Result,
|
||||
}
|
||||
artifacts := InteractionArtifacts{}
|
||||
if req.DiagnosticsWriter != nil {
|
||||
promptMetadata := validatorPromptMetadata(v.validatorType)
|
||||
artifacts, _ = req.DiagnosticsWriter.WriteInteraction(
|
||||
stage,
|
||||
map[string]any{
|
||||
"validator_name": v.name,
|
||||
"validator_type": v.validatorType,
|
||||
"batch_index": batch.BatchIndex,
|
||||
"prompt_metadata": promptMetadata.DiagnosticsMap(),
|
||||
"prompt": completion.Prompt,
|
||||
"response_schema": responseSchema.DiagnosticsMap(),
|
||||
},
|
||||
map[string]any{"messages": messages, "items": batch.Items},
|
||||
response,
|
||||
completion.Prepared,
|
||||
map[string]any{"decoded": response, "final_content": completion.FinalContent, "model": completion.Model},
|
||||
errPayload(err),
|
||||
)
|
||||
}
|
||||
@@ -199,16 +192,6 @@ func errPayload(err error) any {
|
||||
return map[string]any{"error": err.Error()}
|
||||
}
|
||||
|
||||
func resolvedValidationModel(cfg *config.Config, override string) string {
|
||||
if strings.TrimSpace(override) != "" {
|
||||
return strings.TrimSpace(override)
|
||||
}
|
||||
if cfg == nil {
|
||||
return ""
|
||||
}
|
||||
return cfg.EffectiveValidationLLMConfig().Model
|
||||
}
|
||||
|
||||
func BuildLLMValidationRequest(validatorName string, validatorType LLMValidatorType, req Request) (LLMValidationRequest, []Decision) {
|
||||
items := make([]LLMValidationItem, 0, len(req.CandidateProposal))
|
||||
immediate := make([]Decision, 0)
|
||||
@@ -255,23 +238,6 @@ func BuildLLMValidationRequest(validatorName string, validatorType LLMValidatorT
|
||||
}, immediate
|
||||
}
|
||||
|
||||
func promptBuilderForType(validatorType LLMValidatorType) (LLMPromptBuilder, error) {
|
||||
switch validatorType {
|
||||
case LLMValidatorTypeSpokenFormPlausibility:
|
||||
return BuildSpokenFormPlausibilityMessages, nil
|
||||
case LLMValidatorTypeMeaningReversal:
|
||||
return BuildMeaningReversalMessages, nil
|
||||
case LLMValidatorTypeEditorialReview:
|
||||
return BuildEditorialMessages, nil
|
||||
case LLMValidatorTypeGrammarReview:
|
||||
return BuildGrammarReviewMessages, nil
|
||||
case LLMValidatorTypeSpokenWordReview:
|
||||
return BuildSpokenWordReviewMessages, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported LLM validator type %q", validatorType)
|
||||
}
|
||||
}
|
||||
|
||||
func mapLLMResponseToDecisions(items []LLMValidationItem, response LLMValidationResponse) ([]Decision, error) {
|
||||
expected := make(map[int]LLMValidationItem, len(items))
|
||||
for _, item := range items {
|
||||
|
||||
Reference in New Issue
Block a user