feat: add AI Querier module with custom output schema support and refactor common model calling logic

- Add new AI Querier module for structured information extraction from screenshots
- Support custom output schema for structured data response
- Implement automatic type conversion and data validation
- Add comprehensive test suite with various data structure examples
- Refactor callModelWithLogging to utils.go as shared function for planner, asserter, and querier
- Eliminate code duplication across AI modules (30+ lines of repeated code)
- Improve maintainability with unified logging and timing logic
- Add environment variable checks in test setup to handle missing API keys gracefully

Key features:
- Custom output schema support with JSON Schema generation
- Automatic data type conversion with reflection
- Fallback mechanisms for robust parsing
- Comprehensive documentation and usage examples
- Backward compatibility with existing functionality
This commit is contained in:
lilong.129
2025-06-10 20:41:35 +08:00
parent fa9a53d2ae
commit 7c45acd061
10 changed files with 1495 additions and 22 deletions
+2 -8
View File
@@ -3,7 +3,6 @@ package ai
import (
"context"
"fmt"
"time"
"github.com/cloudwego/eino-ext/components/model/openai"
openai2 "github.com/cloudwego/eino-ext/libs/acl/openai"
@@ -15,7 +14,6 @@ import (
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/httprunner/httprunner/v5/uixt/types"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
// IAsserter interface defines the contract for assertion operations
@@ -128,15 +126,11 @@ Here is the assertion. Please tell whether it is truthy according to the screens
a.history.Append(userMsg)
// Call model service, generate response
logRequest(a.history)
startTime := time.Now()
message, err := a.model.Generate(ctx, a.history)
log.Debug().Float64("elapsed(s)", time.Since(startTime).Seconds()).
Str("model", string(a.modelConfig.ModelType)).Msg("call model service for assertion")
message, err := callModelWithLogging(ctx, a.model, a.history,
a.modelConfig.ModelType, "assertion")
if err != nil {
return nil, errors.Wrap(code.LLMRequestServiceError, err.Error())
}
logResponse(message)
// Parse result
result, err := parseAssertionResult(message.Content)