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
@@ -2,7 +2,6 @@ package ai
import (
"context"
"time"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/components/model"
@@ -116,15 +115,11 @@ func (p *Planner) Call(ctx context.Context, opts *PlanningOptions) (result *Plan
p.history.Append(opts.Message)
// call model service, generate response
logRequest(p.history)
startTime := time.Now()
message, err := p.model.Generate(ctx, p.history)
log.Debug().Float64("elapsed(s)", time.Since(startTime).Seconds()).
Str("model", string(p.modelConfig.ModelType)).Msg("call model service for planning")
message, err := callModelWithLogging(ctx, p.model, p.history,
p.modelConfig.ModelType, "planning")
if err != nil {
return nil, errors.Wrap(code.LLMRequestServiceError, err.Error())
}
logResponse(message)
defer func() {
// Extract usage information if available
@@ -174,7 +169,6 @@ func (p *Planner) Call(ctx context.Context, opts *PlanningOptions) (result *Plan
log.Info().
Interface("thought", result.Thought).
Interface("tool_calls", result.ToolCalls).
Float64("elapsed(s)", time.Since(startTime).Seconds()).
Msg("get VLM planning result")
return result, nil
}