mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-05 07:26:55 +08:00
docs: update docs
This commit is contained in:
@@ -1,417 +0,0 @@
|
||||
# HttpRunner UIXT AI 模块
|
||||
|
||||
## 🚀 概述
|
||||
|
||||
HttpRunner UIXT AI 模块是一个集成了多种人工智能服务的 UI 自动化智能引擎,提供基于大语言模型(LLM)的智能规划、断言验证、信息查询、计算机视觉识别等功能,实现真正的智能化 UI 自动化测试。
|
||||
|
||||
## ✨ 核心特性
|
||||
|
||||
### 🎯 智能组件
|
||||
|
||||
- **智能规划器 (Planner)**: 基于视觉语言模型进行 UI 操作规划
|
||||
- **智能断言器 (Asserter)**: 基于视觉语言模型进行断言验证
|
||||
- **智能查询器 (Querier)**: 从屏幕截图中提取结构化信息
|
||||
- **计算机视觉 (CV)**: OCR 文本识别、UI 元素检测、弹窗识别
|
||||
|
||||
### 🔧 灵活配置
|
||||
|
||||
- **统一 API**: 通过 `NewXTDriver` 统一初始化,无需额外函数
|
||||
- **混合模型**: 支持为三个组件分别选择不同的最优模型
|
||||
- **预设配置**: 提供多种推荐配置方案
|
||||
|
||||
## 📖 使用指南
|
||||
|
||||
### 基本用法
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/httprunner/httprunner/v5/uixt"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
// 方式1: 使用单一模型
|
||||
driver, err := uixt.NewXTDriver(mockDriver,
|
||||
option.WithLLMService(option.OPENAI_GPT_4O))
|
||||
|
||||
// 方式2: 使用高级配置 - 为不同组件选择不同模型
|
||||
config := option.NewLLMServiceConfig(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
|
||||
WithPlannerModel(option.DOUBAO_1_5_UI_TARS_250328). // UI理解用UI-TARS
|
||||
WithAsserterModel(option.OPENAI_GPT_4O). // 推理用GPT-4O
|
||||
WithQuerierModel(option.DEEPSEEK_R1_250528) // 查询用DeepSeek
|
||||
|
||||
driver, err := uixt.NewXTDriver(mockDriver,
|
||||
option.WithLLMConfig(config))
|
||||
|
||||
// 方式3: 使用推荐配置
|
||||
configs := option.RecommendedConfigurations()
|
||||
driver, err := uixt.NewXTDriver(mockDriver,
|
||||
option.WithLLMConfig(configs["mixed_optimal"]))
|
||||
```
|
||||
|
||||
### 推荐配置方案
|
||||
|
||||
| 配置名称 | 说明 | 适用场景 |
|
||||
|---------|------|----------|
|
||||
| `cost_effective` | 成本优化配置 | 预算有限的项目 |
|
||||
| `high_performance` | 高性能配置(全部使用GPT-4O) | 对准确性要求极高的场景 |
|
||||
| `mixed_optimal` | 混合优化配置 | 平衡性能和成本的最佳选择 |
|
||||
| `ui_focused` | UI专注配置(全部使用UI-TARS) | UI自动化专项测试 |
|
||||
| `reasoning_focused` | 推理专注配置(全部使用豆包思考模型) | 复杂逻辑推理场景 |
|
||||
|
||||
### 支持的模型
|
||||
|
||||
| 模型名称 | 特点 | 适用组件 |
|
||||
|---------|------|----------|
|
||||
| `DOUBAO_1_5_UI_TARS_250328` | UI理解专业模型 | Planner |
|
||||
| `DOUBAO_1_5_THINKING_VISION_PRO_250428` | 思考推理模型 | Asserter, Querier |
|
||||
| `OPENAI_GPT_4O` | 高性能通用模型 | 全部组件 |
|
||||
| `DEEPSEEK_R1_250528` | 成本效益模型 | Querier |
|
||||
|
||||
## 🔧 环境配置
|
||||
|
||||
### 多模型配置
|
||||
|
||||
支持为不同模型配置独立的环境变量:
|
||||
|
||||
```bash
|
||||
# 豆包思维视觉专业版
|
||||
DOUBAO_1_5_THINKING_VISION_PRO_250428_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||
DOUBAO_1_5_THINKING_VISION_PRO_250428_API_KEY=your_doubao_api_key
|
||||
|
||||
# 豆包UI-TARS
|
||||
DOUBAO_1_5_UI_TARS_250328_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||
DOUBAO_1_5_UI_TARS_250328_API_KEY=your_doubao_ui_tars_api_key
|
||||
|
||||
# OpenAI GPT-4O
|
||||
OPENAI_GPT_4O_BASE_URL=https://api.openai.com/v1
|
||||
OPENAI_GPT_4O_API_KEY=your_openai_api_key
|
||||
|
||||
# DeepSeek
|
||||
DEEPSEEK_R1_250528_BASE_URL=https://api.deepseek.com/v1
|
||||
DEEPSEEK_R1_250528_API_KEY=your_deepseek_api_key
|
||||
```
|
||||
|
||||
### 默认配置
|
||||
|
||||
```bash
|
||||
# 默认配置,当没有找到服务特定配置时使用
|
||||
LLM_MODEL_NAME=doubao-1.5-thinking-vision-pro-250428
|
||||
OPENAI_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||
OPENAI_API_KEY=your_default_api_key
|
||||
```
|
||||
|
||||
### 配置优先级
|
||||
|
||||
1. **服务特定配置**(最高优先级):`{SERVICE_NAME}_BASE_URL`、`{SERVICE_NAME}_API_KEY`
|
||||
2. **默认配置**:`OPENAI_BASE_URL`、`OPENAI_API_KEY`、`LLM_MODEL_NAME`
|
||||
|
||||
## 🏗️ 核心架构
|
||||
|
||||
### 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ UI Driver │ │ AI Module │ │ LLM Services │
|
||||
│ (XTDriver) │◄──►│ (ai package) │◄──►│ (多模型支持) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ CV Services │
|
||||
│ (VEDEM) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### 核心接口
|
||||
|
||||
```go
|
||||
// LLM 服务接口
|
||||
type ILLMService interface {
|
||||
Plan(ctx context.Context, opts *PlanningOptions) (*PlanningResult, error)
|
||||
Assert(ctx context.Context, opts *AssertOptions) (*AssertionResult, error)
|
||||
Query(ctx context.Context, opts *QueryOptions) (*QueryResult, error)
|
||||
RegisterTools(tools []*schema.ToolInfo) error
|
||||
}
|
||||
|
||||
// 计算机视觉服务接口
|
||||
type ICVService interface {
|
||||
ReadFromBuffer(imageBuf *bytes.Buffer, opts ...option.ActionOption) (*CVResult, error)
|
||||
ReadFromPath(imagePath string, opts ...option.ActionOption) (*CVResult, error)
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 功能详解
|
||||
|
||||
### 1. 智能规划 (Planning)
|
||||
|
||||
基于视觉语言模型进行 UI 操作规划,将自然语言指令转换为具体的操作序列。
|
||||
|
||||
```go
|
||||
// 规划选项
|
||||
type PlanningOptions struct {
|
||||
UserInstruction string `json:"user_instruction"` // 用户指令
|
||||
Message *schema.Message `json:"message"` // 消息内容
|
||||
Size types.Size `json:"size"` // 屏幕尺寸
|
||||
ResetHistory bool `json:"reset_history"` // 是否重置历史
|
||||
}
|
||||
|
||||
// 规划结果
|
||||
type PlanningResult struct {
|
||||
ToolCalls []schema.ToolCall `json:"tool_calls"` // 工具调用序列
|
||||
Thought string `json:"thought"` // 思考过程
|
||||
Content string `json:"content"` // 响应内容
|
||||
Error string `json:"error,omitempty"`
|
||||
ModelName string `json:"model_name"`
|
||||
Usage *schema.TokenUsage `json:"usage,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
**使用示例**:
|
||||
```go
|
||||
planResult, err := service.Plan(ctx, &ai.PlanningOptions{
|
||||
UserInstruction: "点击登录按钮",
|
||||
Message: message,
|
||||
Size: screenSize,
|
||||
})
|
||||
```
|
||||
|
||||
### 2. 智能断言 (Assertion)
|
||||
|
||||
基于视觉语言模型进行断言验证,支持自然语言描述的断言条件。
|
||||
|
||||
```go
|
||||
// 断言选项
|
||||
type AssertOptions struct {
|
||||
Assertion string `json:"assertion"` // 断言条件
|
||||
Screenshot string `json:"screenshot"` // 屏幕截图
|
||||
Size types.Size `json:"size"` // 屏幕尺寸
|
||||
}
|
||||
|
||||
// 断言结果
|
||||
type AssertionResult struct {
|
||||
Pass bool `json:"pass"` // 是否通过
|
||||
Thought string `json:"thought"` // 推理过程
|
||||
}
|
||||
```
|
||||
|
||||
**使用示例**:
|
||||
```go
|
||||
assertResult, err := service.Assert(ctx, &ai.AssertOptions{
|
||||
Assertion: "登录按钮应该可见",
|
||||
Screenshot: screenshot,
|
||||
Size: screenSize,
|
||||
})
|
||||
```
|
||||
|
||||
### 3. 智能查询 (Query)
|
||||
|
||||
从屏幕截图中提取结构化信息,支持自定义输出格式。
|
||||
|
||||
```go
|
||||
// 查询选项
|
||||
type QueryOptions struct {
|
||||
Query string `json:"query"` // 查询指令
|
||||
Screenshot string `json:"screenshot"` // 屏幕截图
|
||||
Size types.Size `json:"size"` // 屏幕尺寸
|
||||
OutputSchema interface{} `json:"outputSchema,omitempty"` // 自定义输出格式
|
||||
}
|
||||
|
||||
// 查询结果
|
||||
type QueryResult struct {
|
||||
Content string `json:"content"` // 文本内容
|
||||
Thought string `json:"thought"` // 思考过程
|
||||
Data interface{} `json:"data,omitempty"` // 结构化数据
|
||||
}
|
||||
```
|
||||
|
||||
**基础查询示例**:
|
||||
```go
|
||||
result, err := service.Query(ctx, &ai.QueryOptions{
|
||||
Query: "请描述这张图片中的内容",
|
||||
Screenshot: screenshot,
|
||||
Size: screenSize,
|
||||
})
|
||||
```
|
||||
|
||||
**自定义格式查询示例**:
|
||||
```go
|
||||
type GameInfo struct {
|
||||
Content string `json:"content"`
|
||||
Thought string `json:"thought"`
|
||||
Rows int `json:"rows"`
|
||||
Cols int `json:"cols"`
|
||||
Icons []string `json:"icons"`
|
||||
}
|
||||
|
||||
result, err := service.Query(ctx, &ai.QueryOptions{
|
||||
Query: "分析这个连连看游戏界面",
|
||||
Screenshot: screenshot,
|
||||
Size: screenSize,
|
||||
OutputSchema: GameInfo{},
|
||||
})
|
||||
|
||||
// 直接类型断言获取结构化数据
|
||||
if gameInfo, ok := result.Data.(*GameInfo); ok {
|
||||
fmt.Printf("游戏有 %d 行 %d 列\n", gameInfo.Rows, gameInfo.Cols)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 计算机视觉 (CV)
|
||||
|
||||
提供 OCR 文本识别、UI 元素检测、弹窗识别等计算机视觉功能。
|
||||
|
||||
```go
|
||||
// CV 结果
|
||||
type CVResult struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
OCRResult OCRResults `json:"ocrResult,omitempty"`
|
||||
LiveType string `json:"liveType,omitempty"`
|
||||
LivePopularity int64 `json:"livePopularity,omitempty"`
|
||||
UIResult UIResultMap `json:"uiResult,omitempty"`
|
||||
ClosePopupsResult *ClosePopupsResult `json:"closeResult,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
**使用示例**:
|
||||
```go
|
||||
cvService, err := ai.NewCVService(option.CVServiceTypeVEDEM)
|
||||
cvResult, err := cvService.ReadFromBuffer(imageBuffer)
|
||||
|
||||
// 处理 OCR 结果
|
||||
ocrTexts := cvResult.OCRResult.ToOCRTexts()
|
||||
targetText, err := ocrTexts.FindText("登录", option.WithRegex(false))
|
||||
center := targetText.Center()
|
||||
```
|
||||
|
||||
## 🎨 高级特性
|
||||
|
||||
### 1. 多模型适配
|
||||
|
||||
不同模型具有不同的优势,可以根据场景选择最适合的模型:
|
||||
|
||||
- **UI-TARS**: 专门针对 UI 自动化优化,理解界面元素能力强
|
||||
- **GPT-4O**: 通用性强,推理能力优秀
|
||||
- **豆包思考模型**: 支持深度思考,适合复杂场景分析
|
||||
- **DeepSeek**: 成本效益高,适合大量查询场景
|
||||
|
||||
### 2. 坐标系统转换
|
||||
|
||||
支持多种坐标格式的智能转换:
|
||||
|
||||
- 相对坐标 (0-1000 范围) 转换为绝对像素坐标
|
||||
- 支持 `<point>`、`<bbox>`、`[x,y,x,y]` 等多种格式
|
||||
- 自动处理不同模型的坐标输出差异
|
||||
|
||||
### 3. 智能会话管理
|
||||
|
||||
- **对话历史**: 维护完整的对话上下文
|
||||
- **内存优化**: 自动清理过期的对话记录
|
||||
- **消息管理**: 智能管理用户图像消息和助手回复
|
||||
|
||||
### 4. 自定义输出格式
|
||||
|
||||
查询功能支持用户定义的复杂结构化输出格式:
|
||||
|
||||
```go
|
||||
type UIAnalysisResult struct {
|
||||
Content string `json:"content"`
|
||||
Elements []UIElement `json:"elements"`
|
||||
Statistics Statistics `json:"statistics"`
|
||||
}
|
||||
|
||||
type UIElement struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text"`
|
||||
BoundingBox BoundingBox `json:"boundingBox"`
|
||||
Clickable bool `json:"clickable"`
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 配置参数
|
||||
|
||||
### 模型配置
|
||||
|
||||
| 参数 | 类型 | 说明 | 默认值 |
|
||||
|------|------|------|--------|
|
||||
| `BaseURL` | string | API 基础 URL | 从环境变量读取 |
|
||||
| `APIKey` | string | API 密钥 | 从环境变量读取 |
|
||||
| `Model` | string | 模型名称 | 从环境变量读取 |
|
||||
| `Temperature` | float32 | 温度参数 | 0 |
|
||||
| `TopP` | float32 | Top-P 参数 | 0.7 |
|
||||
| `Timeout` | time.Duration | 请求超时 | 30s |
|
||||
|
||||
### 操作选项
|
||||
|
||||
| 组件 | 必需参数 | 可选参数 |
|
||||
|------|----------|----------|
|
||||
| **Planner** | `UserInstruction`, `Message`, `Size` | `ResetHistory` |
|
||||
| **Asserter** | `Assertion`, `Screenshot`, `Size` | - |
|
||||
| **Querier** | `Query`, `Screenshot`, `Size` | `OutputSchema` |
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 环境配置
|
||||
- 确保所有必需的环境变量都已正确设置
|
||||
- API 密钥需要有足够的权限和配额
|
||||
- 支持多模型配置,可以同时配置多个服务
|
||||
|
||||
### 2. 图像格式
|
||||
- 支持 Base64 编码的图像数据
|
||||
- 推荐使用 JPEG 格式以减少数据传输量
|
||||
- 图像尺寸信息必须准确提供
|
||||
|
||||
### 3. 坐标系统
|
||||
- 不同模型使用不同的坐标系统
|
||||
- 需要正确的屏幕尺寸信息进行坐标转换
|
||||
- 系统会自动处理坐标格式差异
|
||||
|
||||
### 4. 性能考虑
|
||||
- LLM 调用有延迟,适合异步处理
|
||||
- 图像数据较大,注意网络传输优化
|
||||
- 对话历史会占用内存,系统会自动清理
|
||||
|
||||
### 5. 错误处理
|
||||
- 网络请求可能失败,需要适当的重试机制
|
||||
- 模型输出格式可能不稳定,系统提供健壮的解析逻辑
|
||||
- 建议在生产环境中添加监控和告警
|
||||
|
||||
## 🧪 测试数据
|
||||
|
||||
模块包含丰富的测试数据,位于 `testdata/` 目录:
|
||||
|
||||
- `xhs-feed.jpeg`: 小红书信息流界面
|
||||
- `popup_risk_warning.png`: 风险警告弹窗
|
||||
- `llk_*.png`: 连连看游戏界面
|
||||
- `deepseek_*.png`: DeepSeek 应用界面
|
||||
- `chat_list.jpeg`: 聊天列表界面
|
||||
|
||||
这些测试数据覆盖了各种典型的 UI 场景,用于验证 AI 模块的功能正确性。
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
1. **配置环境变量**
|
||||
```bash
|
||||
# 配置默认模型
|
||||
export OPENAI_BASE_URL=https://your-endpoint.com
|
||||
export OPENAI_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
2. **创建驱动**
|
||||
```go
|
||||
driver, err := uixt.NewXTDriver(mockDriver,
|
||||
option.WithLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428))
|
||||
```
|
||||
|
||||
3. **执行智能操作**
|
||||
```go
|
||||
// 智能规划
|
||||
planResult, err := driver.LLMService.Plan(ctx, planningOpts)
|
||||
|
||||
// 智能断言
|
||||
assertResult, err := driver.LLMService.Assert(ctx, assertOpts)
|
||||
|
||||
// 智能查询
|
||||
queryResult, err := driver.LLMService.Query(ctx, queryOpts)
|
||||
```
|
||||
|
||||
通过 HttpRunner UIXT AI 模块,您可以轻松实现智能化的 UI 自动化测试,大幅提升测试效率和准确性。
|
||||
@@ -1,299 +0,0 @@
|
||||
# HttpRunner AI Querier - 自定义输出格式功能
|
||||
|
||||
## 功能概述
|
||||
|
||||
HttpRunner 的 AI Querier 模块支持自定义输出格式功能,允许用户指定特定的数据结构,让 AI 模型返回结构化的数据响应。适用于:
|
||||
|
||||
- **UI 元素分析**:自动化测试中的界面元素提取
|
||||
- **游戏界面分析**:网格类游戏(连连看、消消乐、2048等)数据提取
|
||||
- **表单数据提取**:从表单截图中提取结构化信息
|
||||
- **图像内容分析**:任何需要从截图中提取结构化信息的场景
|
||||
|
||||
## 核心数据结构
|
||||
|
||||
```go
|
||||
// QueryOptions - 查询选项
|
||||
type QueryOptions struct {
|
||||
Query string `json:"query"` // 查询文本
|
||||
Screenshot string `json:"screenshot"` // Base64编码的截图
|
||||
Size types.Size `json:"size"` // 屏幕尺寸
|
||||
OutputSchema interface{} `json:"outputSchema,omitempty"` // 自定义输出格式(可选)
|
||||
}
|
||||
|
||||
// QueryResult - 查询结果
|
||||
type QueryResult struct {
|
||||
Content string `json:"content"` // 人类可读的分析结果
|
||||
Thought string `json:"thought"` // AI 推理过程
|
||||
Data interface{} `json:"data,omitempty"` // 结构化数据(使用OutputSchema时自动转换为指定类型)
|
||||
}
|
||||
```
|
||||
|
||||
## 基本用法
|
||||
|
||||
### 标准查询
|
||||
|
||||
```go
|
||||
// 创建查询器
|
||||
modelConfig, err := ai.GetModelConfig(option.OPENAI_GPT_4O)
|
||||
querier, err := ai.NewQuerier(ctx, modelConfig)
|
||||
|
||||
// 执行查询
|
||||
result, err := querier.Query(ctx, &ai.QueryOptions{
|
||||
Query: "请分析这张截图中的内容",
|
||||
Screenshot: screenshot,
|
||||
Size: size,
|
||||
// 不指定 OutputSchema
|
||||
})
|
||||
|
||||
fmt.Printf("分析结果: %s\n", result.Content)
|
||||
fmt.Printf("推理过程: %s\n", result.Thought)
|
||||
// result.Data 为 nil
|
||||
```
|
||||
|
||||
### 自定义格式查询
|
||||
|
||||
```go
|
||||
// 定义输出结构
|
||||
type GameAnalysis struct {
|
||||
Content string `json:"content"` // 分析描述
|
||||
Thought string `json:"thought"` // 思考过程
|
||||
Rows int `json:"rows"` // 行数
|
||||
Cols int `json:"cols"` // 列数
|
||||
Icons []string `json:"icons"` // 图标类型
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
result, err := querier.Query(ctx, &ai.QueryOptions{
|
||||
Query: "分析这个游戏界面的网格结构和图标类型",
|
||||
Screenshot: screenshot,
|
||||
Size: size,
|
||||
OutputSchema: GameAnalysis{}, // 指定输出格式
|
||||
})
|
||||
|
||||
// 直接类型断言获取结构化数据
|
||||
if gameData, ok := result.Data.(*GameAnalysis); ok {
|
||||
fmt.Printf("行数: %d, 列数: %d\n", gameData.Rows, gameData.Cols)
|
||||
fmt.Printf("图标类型: %v\n", gameData.Icons)
|
||||
}
|
||||
```
|
||||
|
||||
## 应用场景示例
|
||||
|
||||
### UI 元素分析
|
||||
|
||||
```go
|
||||
type UIAnalysis struct {
|
||||
Content string `json:"content"`
|
||||
Thought string `json:"thought"`
|
||||
Elements []UIElement `json:"elements"`
|
||||
}
|
||||
|
||||
type UIElement struct {
|
||||
Type string `json:"type"` // button, text, input等
|
||||
Text string `json:"text"` // 文本内容
|
||||
BoundBox BoundingBox `json:"boundBox"` // 位置坐标
|
||||
Clickable bool `json:"clickable"` // 是否可点击
|
||||
}
|
||||
|
||||
type BoundingBox struct {
|
||||
X, Y, Width, Height int `json:"x,y,width,height"`
|
||||
}
|
||||
```
|
||||
|
||||
### 网格游戏分析
|
||||
|
||||
```go
|
||||
type GridGame struct {
|
||||
Content string `json:"content"`
|
||||
Thought string `json:"thought"`
|
||||
Grid [][]Cell `json:"grid"` // 网格数据
|
||||
Stats Statistics `json:"statistics"` // 统计信息
|
||||
}
|
||||
|
||||
type Cell struct {
|
||||
Type string `json:"type"` // 单元格类型
|
||||
Value string `json:"value"` // 单元格值
|
||||
Row int `json:"row"` // 行索引
|
||||
Col int `json:"col"` // 列索引
|
||||
}
|
||||
|
||||
type Statistics struct {
|
||||
TotalCells int `json:"totalCells"`
|
||||
UniqueTypes int `json:"uniqueTypes"`
|
||||
}
|
||||
```
|
||||
|
||||
### 表单数据提取
|
||||
|
||||
```go
|
||||
type FormAnalysis struct {
|
||||
Content string `json:"content"`
|
||||
Thought string `json:"thought"`
|
||||
Fields []FormField `json:"fields"`
|
||||
Actions []Action `json:"actions"`
|
||||
}
|
||||
|
||||
type FormField struct {
|
||||
Label string `json:"label"` // 字段标签
|
||||
Type string `json:"type"` // 字段类型
|
||||
Value string `json:"value"` // 当前值
|
||||
Required bool `json:"required"` // 是否必填
|
||||
BoundBox BoundingBox `json:"boundBox"` // 位置
|
||||
}
|
||||
```
|
||||
|
||||
## 核心特性
|
||||
|
||||
### 自动类型转换
|
||||
- 指定 `OutputSchema` 时,`QueryResult.Data` 自动转换为指定类型
|
||||
- 支持直接类型断言:`result.Data.(*YourType)`
|
||||
- 无需手动调用转换函数
|
||||
|
||||
### 多级回退机制
|
||||
1. 优先解析为指定的结构化类型
|
||||
2. 失败时尝试通用JSON解析
|
||||
3. 最终回退到纯文本响应
|
||||
|
||||
### 向后兼容
|
||||
- 不指定 `OutputSchema` 时行为不变
|
||||
- 现有代码无需修改
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 结构体设计
|
||||
|
||||
```go
|
||||
// 推荐:包含标准字段
|
||||
type YourSchema struct {
|
||||
Content string `json:"content"` // 必须:人类可读描述
|
||||
Thought string `json:"thought"` // 必须:AI推理过程
|
||||
// 自定义字段...
|
||||
Data CustomData `json:"data"`
|
||||
}
|
||||
|
||||
// 使用描述性的JSON标签
|
||||
type Element struct {
|
||||
Type string `json:"elementType"` // 清晰的字段名
|
||||
Position Point `json:"gridPosition"` // 描述性标签
|
||||
Visible bool `json:"isVisible"` // 布尔值清晰性
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询指令
|
||||
|
||||
```go
|
||||
// 推荐:详细的查询指令
|
||||
opts := &ai.QueryOptions{
|
||||
Query: `分析这张截图并提供结构化信息:
|
||||
1. 识别界面类型和主要元素
|
||||
2. 提取所有可交互元素的位置和属性
|
||||
3. 统计各类元素的数量`,
|
||||
Screenshot: screenshot,
|
||||
Size: size,
|
||||
OutputSchema: YourSchema{},
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 错误处理
|
||||
|
||||
```go
|
||||
result, err := querier.Query(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 类型断言
|
||||
if data, ok := result.Data.(*YourSchema); ok {
|
||||
// 使用结构化数据
|
||||
processData(data)
|
||||
} else {
|
||||
// 回退到文本结果
|
||||
log.Printf("结构化解析失败,使用文本结果: %s", result.Content)
|
||||
}
|
||||
```
|
||||
|
||||
## 完整示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v5/uixt/ai"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
type ScreenAnalysis struct {
|
||||
Content string `json:"content"`
|
||||
Thought string `json:"thought"`
|
||||
Elements []string `json:"elements"`
|
||||
Categories []string `json:"categories"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// 创建查询器
|
||||
modelConfig, err := ai.GetModelConfig(option.OPENAI_GPT_4O)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
querier, err := ai.NewQuerier(ctx, modelConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 加载截图
|
||||
screenshot, size, err := builtin.LoadImage("screenshot.png")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 执行结构化查询
|
||||
result, err := querier.Query(ctx, &ai.QueryOptions{
|
||||
Query: "分析截图中的UI元素,提取元素类型和分类信息",
|
||||
Screenshot: screenshot,
|
||||
Size: size,
|
||||
OutputSchema: ScreenAnalysis{},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 使用结构化数据
|
||||
if analysis, ok := result.Data.(*ScreenAnalysis); ok {
|
||||
fmt.Printf("发现 %d 个元素\n", analysis.Count)
|
||||
fmt.Printf("元素类型: %v\n", analysis.Elements)
|
||||
fmt.Printf("分类: %v\n", analysis.Categories)
|
||||
} else {
|
||||
fmt.Printf("文本结果: %s\n", result.Content)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 辅助函数
|
||||
|
||||
对于特殊情况,提供了类型转换辅助函数:
|
||||
|
||||
```go
|
||||
// 手动类型转换(通常不需要)
|
||||
converted, err := ai.ConvertQueryResultData[YourType](result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:使用 `OutputSchema` 时,`Data` 字段已自动转换为正确类型,通常不需要手动调用此函数。
|
||||
|
||||
## 技术限制
|
||||
|
||||
- 需要支持结构化输出的AI模型(如 OpenAI GPT-4)
|
||||
- 复杂嵌套结构需要清晰的查询指令
|
||||
- AI模型可能不总是严格遵循指定格式
|
||||
- UI-TARS 模型使用不同的响应格式处理
|
||||
Reference in New Issue
Block a user