191 lines
5.5 KiB
Markdown
191 lines
5.5 KiB
Markdown
# 服装搭配搜索功能实现
|
|
|
|
## 概述
|
|
|
|
本文档描述了服装搭配搜索功能的实现,该功能直接调用 Google Vertex AI Search API 进行搜索,而不是通过 RAG Grounding。
|
|
|
|
## 核心功能
|
|
|
|
### 1. 直接 Vertex AI Search 调用
|
|
|
|
- **API 端点**: `https://discoveryengine.googleapis.com/v1beta/projects/{project_id}/locations/global/collections/default_collection/engines/{app_id}/servingConfigs/default_search:search`
|
|
- **认证**: 通过 Google 访问令牌进行认证
|
|
- **数据存储**: 使用配置的 `vertex_ai_app_id` 和 `data_store_id`
|
|
|
|
### 2. 搜索配置
|
|
|
|
```rust
|
|
pub struct SearchRequest {
|
|
pub query: String, // 搜索查询字符串
|
|
pub config: SearchConfig, // 搜索配置
|
|
pub page_size: usize, // 页面大小
|
|
pub page_offset: usize, // 页面偏移量
|
|
}
|
|
|
|
pub struct SearchConfig {
|
|
pub relevance_threshold: RelevanceThreshold, // 相关性阈值
|
|
pub environments: Vec<String>, // 环境标签过滤
|
|
pub categories: Vec<String>, // 类别过滤
|
|
pub color_filters: HashMap<String, ColorFilter>, // 颜色过滤器
|
|
pub design_styles: HashMap<String, Vec<String>>, // 设计风格过滤
|
|
pub max_keywords: usize, // 最大关键词数量
|
|
}
|
|
```
|
|
|
|
### 3. 搜索流程
|
|
|
|
1. **获取访问令牌**: 通过 Modal.run API 获取 Google 访问令牌
|
|
2. **构建搜索过滤器**: 根据搜索配置构建 Vertex AI Search 过滤器
|
|
3. **组合查询字符串**: 将用户查询与关键词组合
|
|
4. **发送 HTTP 请求**: 直接调用 Vertex AI Search API
|
|
5. **解析响应**: 将 Vertex AI 响应转换为应用程序格式
|
|
6. **应用过滤**: 根据相关性阈值过滤结果
|
|
|
|
### 4. 响应格式转换
|
|
|
|
```rust
|
|
pub struct SearchResult {
|
|
pub id: String, // 结果ID
|
|
pub image_url: String, // 图片URL
|
|
pub style_description: String, // 风格描述
|
|
pub environment_tags: Vec<String>, // 环境标签
|
|
pub products: Vec<ProductInfo>, // 产品信息列表
|
|
pub relevance_score: f64, // 相关性评分
|
|
}
|
|
|
|
pub struct ProductInfo {
|
|
pub category: String, // 产品类别
|
|
pub description: String, // 产品描述
|
|
pub color_pattern: ColorHSV, // 主要颜色
|
|
pub design_styles: Vec<String>, // 设计风格
|
|
}
|
|
```
|
|
|
|
## 实现细节
|
|
|
|
### 1. 访问令牌获取
|
|
|
|
```rust
|
|
async fn get_google_access_token() -> Result<String, anyhow::Error> {
|
|
let config = GeminiConfig::default();
|
|
let client = reqwest::Client::new();
|
|
|
|
let url = format!("{}/google/access-token", config.base_url);
|
|
|
|
let response = client
|
|
.get(&url)
|
|
.header("Authorization", format!("Bearer {}", config.bearer_token))
|
|
.send()
|
|
.await?;
|
|
|
|
// 解析访问令牌...
|
|
}
|
|
```
|
|
|
|
### 2. 搜索请求构建
|
|
|
|
```rust
|
|
let mut payload = serde_json::json!({
|
|
"query": enhanced_query,
|
|
"relevanceThreshold": request.config.relevance_threshold.to_value().to_string(),
|
|
"relevanceScoreSpec": {
|
|
"returnRelevanceScore": true
|
|
},
|
|
"pageSize": request.page_size,
|
|
"offset": request.page_offset
|
|
});
|
|
|
|
// 添加过滤器(如果有)
|
|
if !search_filter.is_empty() {
|
|
payload["filter"] = serde_json::Value::String(search_filter);
|
|
}
|
|
```
|
|
|
|
### 3. 响应解析
|
|
|
|
- 从 Vertex AI Search 响应中提取 `results` 数组
|
|
- 解析每个结果的 `document.structData` 字段
|
|
- 提取图片URL、风格描述、环境标签等信息
|
|
- 解析产品信息和颜色模式
|
|
- 获取相关性评分并应用阈值过滤
|
|
|
|
## 配置参数
|
|
|
|
### 全局配置
|
|
|
|
```rust
|
|
impl Default for OutfitSearchGlobalConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
google_project_id: "gen-lang-client-0413414134".to_string(),
|
|
vertex_ai_app_id: "jeans-search_1751353769585".to_string(),
|
|
storage_bucket_name: "fashion_image_block".to_string(),
|
|
data_store_id: "jeans_pattern_data_store".to_string(),
|
|
cloudflare_project_id: "67720b647ff2b55cf37ba3ef9e677083".to_string(),
|
|
cloudflare_gateway_id: "bowong-dev".to_string(),
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 相关性阈值
|
|
|
|
- **LOWEST**: 0.3 - 显示更多相关结果
|
|
- **LOW**: 0.5 - 包含较多相关结果
|
|
- **MEDIUM**: 0.7 - 平衡相关性和数量
|
|
- **HIGH**: 0.9 - 只显示高度相关结果
|
|
|
|
## 错误处理
|
|
|
|
- 访问令牌获取失败
|
|
- HTTP 请求失败
|
|
- JSON 解析错误
|
|
- 数据格式不匹配
|
|
- 网络超时
|
|
|
|
## 测试
|
|
|
|
实现了以下测试用例:
|
|
|
|
1. `test_search_request_creation` - 测试搜索请求创建
|
|
2. `test_search_filter_builder` - 测试搜索过滤器构建
|
|
3. `test_query_keywords_builder` - 测试查询关键词构建
|
|
|
|
## 使用示例
|
|
|
|
```typescript
|
|
import { OutfitSearchService } from '../services/outfitSearchService';
|
|
|
|
const searchRequest = {
|
|
query: "牛仔裤搭配",
|
|
config: {
|
|
relevance_threshold: "HIGH",
|
|
categories: ["上装", "下装"],
|
|
environments: ["Outdoor"],
|
|
color_filters: {},
|
|
design_styles: {},
|
|
max_keywords: 10
|
|
},
|
|
page_size: 9,
|
|
page_offset: 0
|
|
};
|
|
|
|
const response = await OutfitSearchService.searchSimilarOutfits(searchRequest);
|
|
console.log(`找到 ${response.total_size} 个搜索结果`);
|
|
```
|
|
|
|
## 性能优化
|
|
|
|
- 使用连接池减少HTTP连接开销
|
|
- 实现访问令牌缓存机制
|
|
- 支持分页查询避免大量数据传输
|
|
- 客户端相关性过滤减少无效结果
|
|
|
|
## 未来改进
|
|
|
|
1. 添加向量搜索支持
|
|
2. 实现搜索结果缓存
|
|
3. 支持更复杂的过滤条件
|
|
4. 添加搜索分析和统计
|
|
5. 实现搜索建议优化
|