refactor: json asserter

This commit is contained in:
lilong.129
2025-05-22 18:22:12 +08:00
parent c377664518
commit 3b77ade24f
5 changed files with 10 additions and 73 deletions
+1 -1
View File
@@ -1 +1 @@
v5.0.0-beta-2505221534 v5.0.0-beta-2505221822
+6 -8
View File
@@ -54,8 +54,8 @@ func NewAsserter(ctx context.Context, modelConfig *ModelConfig) (*Asserter, erro
} }
if modelConfig.ModelType == option.LLMServiceTypeUITARS { if modelConfig.ModelType == option.LLMServiceTypeUITARS {
asserter.systemPrompt += "\n\n" + uiTarsAssertionResponseFormat asserter.systemPrompt += "\n" + uiTarsAssertionResponseFormat
} else if modelConfig.ModelType == option.LLMServiceTypeDoubaoVL { } else {
// define output format // define output format
type OutputFormat struct { type OutputFormat struct {
Thought string `json:"thought"` Thought string `json:"thought"`
@@ -77,8 +77,6 @@ func NewAsserter(ctx context.Context, modelConfig *ModelConfig) (*Asserter, erro
Strict: false, Strict: false,
}, },
} }
} else {
asserter.systemPrompt += "\n\n" + defaultAssertionResponseJsonFormat
} }
var err error var err error
@@ -134,16 +132,16 @@ Here is the assertion. Please tell whether it is truthy according to the screens
// Call model service, generate response // Call model service, generate response
logRequest(a.history) logRequest(a.history)
startTime := time.Now() startTime := time.Now()
resp, err := a.model.Generate(ctx, a.history) message, err := a.model.Generate(ctx, a.history)
log.Info().Float64("elapsed(s)", time.Since(startTime).Seconds()). log.Info().Float64("elapsed(s)", time.Since(startTime).Seconds()).
Str("model", string(a.modelConfig.ModelType)).Msg("call model service for assertion") Str("model", string(a.modelConfig.ModelType)).Msg("call model service for assertion")
if err != nil { if err != nil {
return nil, errors.Wrap(code.LLMRequestServiceError, err.Error()) return nil, errors.Wrap(code.LLMRequestServiceError, err.Error())
} }
logResponse(resp) logResponse(message)
// Parse result // Parse result
result, err := parseAssertionResult(resp.Content) result, err := parseAssertionResult(message.Content)
if err != nil { if err != nil {
return nil, errors.Wrap(code.LLMParseAssertionResponseError, err.Error()) return nil, errors.Wrap(code.LLMParseAssertionResponseError, err.Error())
} }
@@ -151,7 +149,7 @@ Here is the assertion. Please tell whether it is truthy according to the screens
// Append assistant message to history // Append assistant message to history
a.history.Append(&schema.Message{ a.history.Append(&schema.Message{
Role: schema.Assistant, Role: schema.Assistant,
Content: resp.Content, Content: message.Content,
}) })
return result, nil return result, nil
+2 -8
View File
@@ -3,15 +3,9 @@ package ai
// Default assertion system prompt // Default assertion system prompt
const defaultAssertionPrompt = `You are a senior testing engineer. User will give an assertion and a screenshot of a page. By carefully viewing the screenshot, please tell whether the assertion is truthy.` const defaultAssertionPrompt = `You are a senior testing engineer. User will give an assertion and a screenshot of a page. By carefully viewing the screenshot, please tell whether the assertion is truthy.`
// Default assertion response format
const defaultAssertionResponseJsonFormat = `Return in the following JSON format:
{
pass: boolean, // whether the assertion is truthy
thought: string | null, // string, if the result is falsy, give the reason why it is falsy. Otherwise, put null.
}`
// UI-TARS assertion response format // UI-TARS assertion response format
const uiTarsAssertionResponseFormat = `## Output Json String Format const uiTarsAssertionResponseFormat = `
## Output Json String Format
` + "```" + ` ` + "```" + `
"{ "{
"pass": <<is a boolean value from the enum [true, false], true means the assertion is truthy>>, "pass": <<is a boolean value from the enum [true, false], true means the assertion is truthy>>,
+1 -52
View File
@@ -27,14 +27,10 @@ func NewLLMContentParser(modelType option.LLMServiceType) LLMContentParser {
return &UITARSContentParser{ return &UITARSContentParser{
systemPrompt: uiTarsPlanningPrompt, systemPrompt: uiTarsPlanningPrompt,
} }
case option.LLMServiceTypeDoubaoVL: default:
return &JSONContentParser{ return &JSONContentParser{
systemPrompt: defaultPlanningResponseJsonFormat, systemPrompt: defaultPlanningResponseJsonFormat,
} }
default:
return &DefaultContentParser{
systemPrompt: defaultPlanningResponseStringFormat,
}
} }
} }
@@ -433,50 +429,3 @@ func normalizeAction(action *ParsedAction) error {
return nil return nil
} }
// DefaultContentParser parses the response as string format
type DefaultContentParser struct {
systemPrompt string
}
func (p *DefaultContentParser) SystemPrompt() string {
return p.systemPrompt
}
func (p *DefaultContentParser) Parse(content string, size types.Size) (*PlanningResult, error) {
content = strings.TrimSpace(content)
if strings.HasPrefix(content, "```json") && strings.HasSuffix(content, "```") {
content = strings.TrimPrefix(content, "```json")
content = strings.TrimSuffix(content, "```")
}
content = strings.TrimSpace(content)
var response PlanningResult
if err := json.Unmarshal([]byte(content), &response); err != nil {
return nil, fmt.Errorf("failed to parse VLM response: %v", err)
}
if response.Error != "" {
return nil, errors.New(response.Error)
}
if len(response.NextActions) == 0 {
return nil, errors.New("no actions returned from VLM")
}
// normalize actions
var normalizedActions []ParsedAction
for i := range response.NextActions {
// create a new variable, avoid implicit memory aliasing in for loop.
action := response.NextActions[i]
if err := normalizeAction(&action); err != nil {
return nil, errors.Wrap(err, "failed to normalize action")
}
normalizedActions = append(normalizedActions, action)
}
return &PlanningResult{
NextActions: normalizedActions,
ActionSummary: response.ActionSummary,
}, nil
}
-4
View File
@@ -38,7 +38,3 @@ Thought: ...
Action: ... Action: ...
` + "```" + ` ` + "```" + `
` `
const defaultPlanningResponseStringFormat = `
You are a helpful assistant.
`