smithery.ai

product-recommendation

基于用户皮肤档案和社区数据,生成个性化产品推荐。实现产品推荐功能时使用此技能。

First seen Apr 2, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,606 B
  • docs SUMMARY.md 147 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

产品推荐技能

概述

结合用户皮肤档案、社区验证数据和AI分析,生成个性化、可信的产品推荐。

推荐算法

class ProductRecommendationEngine {
    
    /// 主推荐函数
    func recommend(
        for user: UserProfile,
        category: ProductCategory? = nil,
        priceRange: PriceRange? = nil,
        limit: Int = 20
    ) async -> [ProductRecommendation] {
        // 1. 获取候选产品
        var candidates = await productDatabase.getProducts(
            category: category,
            priceRange: priceRange
        )
        
        // 2. 排除用户过敏成分
        candidates = filterOutAllergens(candidates, user.allergies)
        
        // 3. 排除用户不喜欢的品牌
        candidates = filterOutBrands(candidates, user.dislikedBrands)
        
        // 4. 计算推荐分数
        let scored = await calculateScores(candidates, for: user)
        
        // 5. 排序并返回
        return scored
            .sorted { $0.score > $1.score }
            .prefix(limit)
            .map { $0 }
    }
    
    private func calculateScores(
        _ products: [Product],
        for user: UserProfile
    ) async -> [ProductRecommendation] {
        // 获取用户的皮肤双胞胎
        let skinTwins = await skinMatcher.findSkinTwins(for: user.fingerprint)
        
        return products.map { product in
            var score: Double = 0
            var reasons: [String] = []
            var warnings: [String] = []
            
            // 权重配置
            let weights = RecommendationWeights()
            
            // 1. 相似用户有效率 (40%)
            let communityScore = calculateCommunityScore(product, skinTwins)
            score += communityScore.value * weights.community
            if let reason = communityScore.reason { reasons.append(reason) }
            
            // 2. 成分适配度 (30%)
            let ingredientScore = calculateIngredientScore(product, user)
            score += ingredientScore.value * weights.ingredient
            if let reason = ingredientScore.reason { reasons.append(reason) }
            if let warning = ingredientScore.warning { warnings.append(warning) }
            
            // 3. 问题针对性 (20%)
            let concernScore = calculateConcernScore(product, user.concerns)
            score += concernScore.value * weights.concern
            if let reason = concernScore.reason { reasons.append(reason) }
            
            // 4. 刺激风险 (-10%)
            let riskScore = calculateRiskScore(product, user)
            score -= riskScore.value * weights.risk
            if let warning = riskScore.warning { warnings.append(warning) }
            
            return ProductRecommendation(
                product: product,
                score: min(1.0, max(0, score)),
                reasons: reasons,
                warnings: warnings.isEmpty ? nil : warnings,
                communityData: communityScore.data
            )
        }
    }
}

struct RecommendationWeights {
    let community: Double = 0.4     // 社区验证
    let ingredient: Double = 0.3    // 成分适配
    let concern: Double = 0.2       // 问题针对
    let risk: Double = 0.1          // 刺激风险
}

各维度评分详解

社区验证分数

struct CommunityScoreResult {
    let value: Double
    let reason: String?
    let data: CommunityData?
}

struct CommunityData: Codable {
    let effectiveRate: Double       // 有效率
    let sampleSize: Int             // 样本量
    let confidenceInterval: Double  // 置信区间
    let avgImprovementDays: Double  // 平均起效天数
}

func calculateCommunityScore(
    _ product: Product,
    _ skinTwins: [SkinTwin]
) -> CommunityScoreResult {
    let relevantData = skinTwins.compactMap { twin in
        twin.effectiveProducts.first { $0.product.id == product.id }
    }
    
    guard relevantData.count >= 3 else {
        // 样本量不足,返回中性分数
        return CommunityScoreResult(value: 0.5, reason: nil, data: nil)
    }
    
    let totalSimilarity = skinTwins
        .filter { $0.effectiveProducts.contains { $0.product.id == product.id } }
        .reduce(0.0) { $0 + $1.similarity }
    
    let weightedEffectiveness = relevantData.reduce(0.0) { sum, data in
        sum + data.improvementPercent
    } / Double(relevantData.count)
    
    let effectiveRate = Double(relevantData.filter { $0.improvementPercent > 10 }.count) / Double(relevantData.count)
    
    let data = CommunityData(
        effectiveRate: effectiveRate,
        sampleSize: relevantData.count,
        confidenceInterval: calculateCI(relevantData.count),
        avgImprovementDays: relevantData.reduce(0.0) { $0 + Double($1.usageDuration) } / Double(relevantData.count)
    )
    
    let reason = "\(Int(effectiveRate * 100))%相似用户验证有效(\(relevantData.count)人)"
    
    return CommunityScoreResult(
        value: weightedEffectiveness / 100,
        reason: reason,
        data: data
    )
}

成分适配分数

func calculateIngredientScore(
    _ product: Product,
    _ user: UserProfile
) -> (value: Double, reason: String?, warning: String?) {
    var score: Double = 0.5 // 基准分
    var reason: String?
    var warning: String?
    
    // 检查有益成分
    let beneficialIngredients = product.ingredients.filter { ingredient in
        isIngredientBeneficial(ingredient, for: user.skinType, concerns: user.concerns)
    }
    
    if !beneficialIngredients.isEmpty {
        score += 0.3 * min(1.0, Double(beneficialIngredients.count) / 3)
        reason = "含有\(beneficialIngredients.prefix(2).map(\.name).joined(separator: "、"))"
    }
    
    // 检查风险成分
    let riskyIngredients = product.ingredients.filter { ingredient in
        isIngredientRisky(ingredient, for: user.skinType)
    }
    
    if !riskyIngredients.isEmpty {
        score -= 0.2 * min(1.0, Double(riskyIngredients.count) / 2)
        warning = "含\(riskyIngredients.first!.name),\(user.skinType.rawValue)肤质需注意"
    }
    
    return (max(0, min(1, score)), reason, warning)
}

推荐结果模型

struct ProductRecommendation: Identifiable {
    let id = UUID()
    let product: Product
    let score: Double               // 0-1
    let reasons: [String]           // 推荐理由
    let warnings: [String]?         // 风险提示
    let communityData: CommunityData?
    
    /// 是否有足够的社区数据支撑
    var hasCommunityValidation: Bool {
        guard let data = communityData else { return false }
        return data.sampleSize >= 10
    }
    
    /// 推荐强度标签
    var strengthLabel: String {
        switch score {
        case 0.8...: return "强烈推荐"
        case 0.6..<0.8: return "推荐"
        case 0.4..<0.6: return "可考虑"
        default: return "谨慎选择"
        }
    }
}

透明度展示

struct RecommendationTransparency: View {
    let recommendation: ProductRecommendation
    
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            // 推荐分数可视化
            ScoreBar(score: recommendation.score)
            
            // 推荐理由
            ForEach(recommendation.reasons, id: \.self) { reason in
                Label(reason, systemImage: "checkmark.circle.fill")
                    .foregroundColor(.green)
            }
            
            // 风险提示
            if let warnings = recommendation.warnings {
                ForEach(warnings, id: \.self) { warning in
                    Label(warning, systemImage: "exclamationmark.triangle.fill")
                        .foregroundColor(.orange)
                }
            }
            
            // 社区数据
            if let data = recommendation.communityData {
                CommunityDataView(data: data)
            } else {
                Text("暂无社区验证数据,推荐基于AI分析")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
            
            // 商业披露
            if recommendation.product.isSponsored {
                Label("品牌合作", systemImage: "info.circle")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
        }
    }
}

struct CommunityDataView: View {
    let data: CommunityData
    
    var body: some View {
        VStack(alignment: .leading, spacing: 4) {
            Text("社区验证数据")
                .font(.caption)
                .fontWeight(.medium)
            
            HStack {
                StatItem(label: "有效率", value: "\(Int(data.effectiveRate * 100))%")
                StatItem(label: "样本量", value: "\(data.sampleSize)人")
                StatItem(label: "平均起效", value: "\(Int(data.avgImprovementDays))天")
            }
            
            Text("95%置信区间")
                .font(.caption2)
                .foregroundColor(.secondary)
        }
        .padding()
        .background(Color.secondary.opacity(0.1))
        .cornerRadius(8)
    }
}

商业化隔离

/// 推荐排序与商业化完全隔离
/// 商业合作只影响展示位置,不影响推荐分数

struct RecommendationPresenter {
    func present(
        recommendations: [ProductRecommendation],
        sponsoredProducts: [Product]
    ) -> [DisplayItem] {
        var items: [DisplayItem] = []
        
        // 推荐产品按分数排序(不受商业影响)
        let sortedRecommendations = recommendations
            .sorted { $0.score > $1.score }
            .enumerated()
            .map { DisplayItem.recommendation($0.element, rank: $0.offset + 1) }
        
        items.append(contentsOf: sortedRecommendations)
        
        // 商业产品单独展示区域(明确标注)
        if !sponsoredProducts.isEmpty {
            items.append(.sponsoredSection(sponsoredProducts))
        }
        
        return items
    }
}

enum DisplayItem {
    case recommendation(ProductRecommendation, rank: Int)
    case sponsoredSection([Product])
}

验证

  • 推荐分数计算准确
  • 排序不受商业影响
  • 透明度展示完整
  • 社区数据正确统计
  • 用户过滤正确应用