mixvideo-v2/docs/outfit-matching-search-syst...

10 KiB
Raw Blame History

服装搭配智能搜索系统设计文档

概述

基于promptx/outfit-match的Python实现设计一个集成到Tauri桌面应用的服装搭配智能搜索系统。该系统的核心功能是用户上传服装图片 → AI分析提取特征 → 在数据库中搜索相似商品 → 提供LLM驱动的情景搭配建议。

核心功能流程

1. 图像分析流程

用户上传图片 → Gemini API分析 → 提取颜色/风格/类别 → 生成搜索条件 → 显示解析结果

2. 智能搜索流程

解析结果 → 构建搜索过滤器 → Vertex AI Search → 返回相似商品 → 分页展示结果

3. LLM问答流程

用户输入情景 → RAG检索相关数据 → LLM生成搭配建议 → 展示推荐结果

系统架构设计

前端架构 (React + TypeScript)

src/pages/OutfitSearch.tsx           # 主搜索页面
src/components/outfit/
├── ImageUploader.tsx               # 图片上传组件
├── AnalysisResult.tsx              # AI分析结果展示
├── SearchPanel.tsx                 # 搜索配置面板
├── SearchResults.tsx               # 搜索结果展示
├── ColorPicker.tsx                 # 颜色选择器
├── FilterPanel.tsx                 # 筛选条件面板
└── LLMChat.tsx                     # LLM问答组件

后端架构 (Rust)

src/data/models/
├── outfit_search.rs                # 搜索相关数据模型
└── gemini_analysis.rs              # Gemini分析结果模型

src/business/services/
├── gemini_service.rs               # Gemini API集成服务
├── outfit_search_service.rs        # 搜索引擎服务
└── vertex_ai_service.rs            # Vertex AI Search集成

src/presentation/commands/
└── outfit_search_commands.rs       # Tauri命令接口

核心数据模型

Gemini分析结果模型

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutfitAnalysisResult {
    pub environment_tags: Vec<String>,
    pub environment_color_pattern: ColorHSV,
    pub dress_color_pattern: ColorHSV,
    pub style_description: String,
    pub products: Vec<ProductAnalysis>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProductAnalysis {
    pub category: String,
    pub description: String,
    pub color_pattern: ColorHSV,
    pub design_styles: Vec<String>,
    pub color_pattern_match_dress: f64,
    pub color_pattern_match_environment: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ColorHSV {
    pub hue: f64,        // 色相 (0-1)
    pub saturation: f64, // 饱和度 (0-1)
    pub value: f64,      // 明度 (0-1)
}

搜索配置模型

#[derive(Debug, Clone, Serialize, Deserialize)]
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,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ColorFilter {
    pub enabled: bool,
    pub color: ColorHSV,
    pub hue_threshold: f64,
    pub saturation_threshold: f64,
    pub value_threshold: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RelevanceThreshold {
    LOWEST,
    LOW,
    MEDIUM,
    HIGH,
}

搜索结果模型

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResponse {
    pub results: Vec<SearchResult>,
    pub total_size: usize,
    pub next_page_token: Option<String>,
    pub search_time_ms: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResult {
    pub id: String,
    pub image_url: String,
    pub style_description: String,
    pub environment_tags: Vec<String>,
    pub products: Vec<ProductInfo>,
    pub relevance_score: f64,
}

API接口设计

Tauri命令接口

// 图像分析
#[tauri::command]
pub async fn analyze_outfit_image(
    state: State<'_, AppState>,
    image_path: String,
) -> Result<OutfitAnalysisResult, String>;

// 智能搜索
#[tauri::command]
pub async fn search_similar_outfits(
    state: State<'_, AppState>,
    config: SearchConfig,
) -> Result<SearchResponse, String>;

// LLM问答
#[tauri::command]
pub async fn ask_llm_outfit_advice(
    state: State<'_, AppState>,
    user_input: String,
) -> Result<String, String>;

// 获取搜索建议
#[tauri::command]
pub async fn get_search_suggestions(
    state: State<'_, AppState>,
    query: String,
) -> Result<Vec<String>, String>;

核心算法实现

HSV颜色匹配算法

impl ColorHSV {
    pub fn from_rgb_hex(hex: &str) -> Result<Self> {
        // RGB转HSV实现
    }
    
    pub fn to_rgb_hex(&self) -> String {
        // HSV转RGB实现
    }
    
    pub fn is_in_range(&self, other: &ColorHSV, thresholds: &ColorThresholds) -> bool {
        let hue_diff = (self.hue - other.hue).abs();
        let sat_diff = (self.saturation - other.saturation).abs();
        let val_diff = (self.value - other.value).abs();
        
        hue_diff <= thresholds.hue &&
        sat_diff <= thresholds.saturation &&
        val_diff <= thresholds.value
    }
}

搜索过滤器构建

impl SearchFilterBuilder {
    pub fn build_filters(config: &SearchConfig) -> String {
        let mut filters = Vec::new();
        
        // 类别过滤
        if !config.categories.is_empty() {
            for category in &config.categories {
                let mut inner_filters = vec![
                    format!("products.category: ANY(\"{}\")", category)
                ];
                
                // 颜色过滤
                if let Some(color_filter) = config.color_filters.get(category) {
                    if color_filter.enabled {
                        inner_filters.extend(Self::build_color_filters(color_filter));
                    }
                }
                
                // 设计风格过滤
                if let Some(styles) = config.design_styles.get(category) {
                    if !styles.is_empty() {
                        let styles_str = styles.iter()
                            .map(|s| format!("\"{}\"", s))
                            .collect::<Vec<_>>()
                            .join(",");
                        inner_filters.push(format!("products.design_styles: ANY({})", styles_str));
                    }
                }
                
                filters.push(format!("({})", inner_filters.join(" AND ")));
            }
        }
        
        // 环境标签过滤
        if !config.environments.is_empty() {
            let env_str = config.environments.iter()
                .map(|e| format!("\"{}\"", e))
                .collect::<Vec<_>>()
                .join(",");
            filters.push(format!("environment_tags: ANY({})", env_str));
        }
        
        filters.join(" AND ")
    }
}

用户界面设计

主搜索页面布局

export const OutfitSearch: React.FC = () => {
  return (
    <div className="outfit-search-container">
      <div className="search-panel">
        <ImageUploader onAnalysisComplete={handleAnalysis} />
        <SearchPanel config={searchConfig} onConfigChange={updateConfig} />
        <LLMChat onAskLLM={handleLLMQuery} />
      </div>
      
      <div className="results-panel">
        <SearchResults 
          results={searchResults} 
          onPageChange={handlePageChange}
        />
      </div>
    </div>
  );
};

搜索配置面板

export const SearchPanel: React.FC<SearchPanelProps> = ({ config, onConfigChange }) => {
  return (
    <div className="search-config">
      <div className="relevance-threshold">
        <label>匹配严格程度</label>
        <select value={config.relevance_threshold} onChange={handleThresholdChange}>
          <option value="LOWEST">最低</option>
          <option value="LOW"></option>
          <option value="MEDIUM">中等</option>
          <option value="HIGH"></option>
        </select>
      </div>
      
      <div className="category-filters">
        {config.categories.map(category => (
          <CategoryFilter 
            key={category}
            category={category}
            colorFilter={config.color_filters[category]}
            designStyles={config.design_styles[category]}
            onFilterChange={handleFilterChange}
          />
        ))}
      </div>
      
      <button onClick={handleSearch}>搜索</button>
    </div>
  );
};

集成方案

与现有系统集成

  1. 导航系统集成: 搜索功能作为顶部导航栏的独立页面,类似现有的"模特管理"、"AI分类设置"等
  2. AI分类系统复用: 复用现有的Gemini API集成和提示词生成逻辑
  3. 配置管理: project_id等配置作为全局环境变量或应用配置不依赖具体项目
  4. 状态管理: 使用现有的Zustand状态管理模式

配置管理

// 全局配置结构
#[derive(Debug, Clone)]
pub struct OutfitSearchConfig {
    pub google_project_id: String,        // "gen-lang-client-0413414134"
    pub vertex_ai_app_id: String,         // "jeans-search_1751353769585"
    pub storage_bucket_name: String,      // "fashion_image_block"
    pub data_store_id: String,            // "jeans_pattern_data_store"
    pub cloudflare_project_id: String,    // "67720b647ff2b55cf37ba3ef9e677083"
    pub cloudflare_gateway_id: String,    // "bowong-dev"
}

impl Default for OutfitSearchConfig {
    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(),
        }
    }
}

部署配置

  1. 环境变量: 配置Google Cloud访问令牌、Cloudflare网关等
  2. 依赖管理: 添加必要的Rust crates和npm包
  3. 构建配置: 更新Tauri配置以支持网络访问权限

开发优先级

P0 (核心功能)

  • Gemini API集成和图像分析
  • 基础搜索界面和结果展示
  • HSV颜色匹配算法

P1 (完整功能)

  • Vertex AI Search集成
  • 高级搜索过滤器
  • LLM问答功能

P2 (优化功能)

  • 搜索历史和偏好
  • 性能优化和缓存
  • 用户体验改进