UNPKG

@thinking-models/mcp-server

Version:

A Model Context Protocol (MCP) server for thinking models

236 lines (235 loc) 9.62 kB
/** * 相似度计算引擎 - 用于统一各工具间的相似度计算逻辑 */ import { calculateSemanticSimilarity } from './semantic_similarity_local.js'; import { log } from './utils.js'; /** 默认基础匹配权重 */ export const DEFAULT_BASIC_WEIGHTS = { category: 3, subcategory: 1, tag: 2, keyword: 1.5, text: 1, problem: 2, use_case: 1, semantic: 3 }; /** 增强版匹配权重 */ export const DEFAULT_ENHANCED_WEIGHTS = { category: 3, subcategory: 1, tag: 1.5, keyword: 2, text: 1, problem: 3, use_case: 1.5, semantic: 4 }; /** * 计算模型间的相似度 * @param params 相似度计算参数 * @returns 相似度计算结果 */ export async function calculateModelSimilarity(params) { const { sourceModel, targetModel, weights: userWeights = {}, useSemanticSimilarity = true } = params; // 合并用户权重与默认权重 const weights = { ...DEFAULT_BASIC_WEIGHTS, ...userWeights }; if (!sourceModel || !targetModel) { return { score: 0, reasons: [] }; } let score = 0; const reasons = []; // 1. 分类相关度 if (sourceModel.category === targetModel.category && sourceModel.category) { score += weights.category; reasons.push(`同属于「${sourceModel.category}」分类`); } // 2. 子分类相关度 const source_subcats = new Set(sourceModel.subcategories || []); const common_subcats = (targetModel.subcategories || []) .filter(subcat => source_subcats.has(subcat)); if (common_subcats.length > 0) { score += common_subcats.length * weights.subcategory; reasons.push(`共同的子分类:${common_subcats.join(", ")}`); } // 3. 标签相关度 const source_tags = new Set(sourceModel.tags || []); const common_tags = (targetModel.tags || []) .filter(tag => source_tags.has(tag)); if (common_tags.length > 0) { score += common_tags.length * weights.tag; reasons.push(`共同的标签:${common_tags.join(", ")}`); } // 4. 使用场景相关度 const source_use_cases = new Set(sourceModel.use_cases || []); const common_use_cases = (targetModel.use_cases || []) .filter(use_case => source_use_cases.has(use_case)); if (common_use_cases.length > 0) { score += common_use_cases.length * weights.use_case; reasons.push(`适用于相同场景:${common_use_cases.join(", ")}`); } // 5. 问题解决关键词相似度 const source_problem_keywords = new Set(sourceModel.common_problems_solved?.flatMap(p => p.keywords.map(k => k.toLowerCase())) || []); const target_problem_keywords = targetModel.common_problems_solved?.flatMap(p => p.keywords.map(k => k.toLowerCase())) || []; const common_problem_keywords = target_problem_keywords .filter(keyword => source_problem_keywords.has(keyword)); if (common_problem_keywords.length > 0) { score += common_problem_keywords.length * weights.problem; reasons.push(`解决相似问题的关键词:${common_problem_keywords.join(", ")}`); } // 6. 语义相似度计算(如果启用) if (useSemanticSimilarity) { // 定义和目的的文本相似度 if (sourceModel.definition && targetModel.definition) { try { const defSimilarity = await calculateSemanticSimilarity(sourceModel.definition, targetModel.definition); if (defSimilarity > 0.4) { // 只有当相似度超过阈值才计分 const similarityContribution = defSimilarity * weights.semantic; score += similarityContribution; reasons.push(`定义内容相似 (相似度: ${defSimilarity.toFixed(2)})`); } } catch (error) { log(`计算语义相似度时出错: ${error instanceof Error ? error.message : String(error)}`); } } // 解决的问题描述语义相似度 const source_problem_descriptions = sourceModel.common_problems_solved ?.map(p => p.problem_description) .filter(desc => desc && desc.trim() !== "") .join("\n---\n"); const target_problem_descriptions = targetModel.common_problems_solved ?.map(p => p.problem_description) .filter(desc => desc && desc.trim() !== "") .join("\n---\n"); if (source_problem_descriptions && target_problem_descriptions) { try { const semanticSimilarityScore = await calculateSemanticSimilarity(source_problem_descriptions, target_problem_descriptions); if (semanticSimilarityScore > 0.4) { const similarityContribution = semanticSimilarityScore * weights.semantic; score += similarityContribution; reasons.push(`解决的问题主题相似 (相似度: ${semanticSimilarityScore.toFixed(2)})`); } } catch (error) { log(`计算问题描述语义相似度时出错: ${error instanceof Error ? error.message : String(error)}`); } } } // 如果没有找到具体原因,增加一个通用原因 if (reasons.length === 0 && score > 0) { reasons.push("整体特征相似度较高"); } return { score, reasons }; } /** * 根据关键词计算模型的相关度 * @param model 要评估的模型 * @param keywords 关键词数组 * @param weights 权重配置 * @returns 相关度计算结果 */ export function calculateKeywordRelevance(model, keywords, userWeights = {}) { // 合并用户权重与默认权重 const weights = { ...DEFAULT_BASIC_WEIGHTS, ...userWeights }; let score = 0; const reasons = []; const keywordsLower = keywords.map(k => k.toLowerCase()); // 匹配 common_problems_solved.keywords if (model.common_problems_solved) { for (const prob of model.common_problems_solved) { const matched = keywordsLower.filter(k => prob.keywords.map(x => x.toLowerCase()).includes(k)); if (matched.length > 0) { score += matched.length * weights.problem; reasons.push(`问题关键词匹配: ${matched.join(", ")}`); } // 匹配 problem_description for (const k of keywordsLower) { if (prob.problem_description.toLowerCase().includes(k)) { score += weights.text; reasons.push(`问题描述包含: ${k}`); } } } } // 匹配 name for (const k of keywordsLower) { if (model.name.toLowerCase().includes(k)) { score += 2; reasons.push(`模型名称包含: ${k}`); } } // 匹配 tags if (model.tags) { const matched = keywordsLower.filter(k => model.tags.map(x => x.toLowerCase()).includes(k)); if (matched.length > 0) { score += matched.length * weights.tag; reasons.push(`标签匹配: ${matched.join(", ")}`); } } // 匹配 definition if (model.definition) { for (const k of keywordsLower) { if (model.definition.toLowerCase().includes(k)) { score += weights.text; reasons.push(`核心定义包含: ${k}`); } } } return { score, reasons }; } /** * 基于字符串查询计算模型的匹配度 * @param model 要评估的模型 * @param query 查询字符串 * @returns 匹配度计算结果 */ export function calculateQueryMatch(model, query) { let score = 0; const reasons = []; const query_lower = query.toLowerCase(); // 基本信息匹配 if (model.name.toLowerCase().includes(query_lower)) { score += 3; reasons.push("模型名称"); } if (model.definition?.toLowerCase().includes(query_lower)) { score += 2; reasons.push("核心定义"); } if (model.tags?.some(tag => tag.toLowerCase().includes(query_lower))) { score += 2; reasons.push("标签"); } // 科普教学内容匹配 if (model.popular_science_teaching?.some(teaching => teaching.concept_name.toLowerCase().includes(query_lower) || teaching.explanation.toLowerCase().includes(query_lower))) { score += 1; reasons.push("科普教学内容"); } // 局限性匹配 if (model.limitations?.some(limitation => limitation.limitation_name.toLowerCase().includes(query_lower) || limitation.description.toLowerCase().includes(query_lower))) { score += 1; reasons.push("局限性说明"); } // 常见误区匹配 if (model.common_pitfalls?.some(pitfall => pitfall.pitfall_name.toLowerCase().includes(query_lower) || pitfall.description.toLowerCase().includes(query_lower))) { score += 1; reasons.push("常见误区"); } // 能解决的问题 if (model.common_problems_solved?.some(problem => problem.problem_description.toLowerCase().includes(query_lower) || problem.keywords.some(k => k.toLowerCase().includes(query_lower)))) { score += 2; reasons.push("能解决的问题或关键词"); } // 可视化 if (model.visualizations?.some(viz => viz.title.toLowerCase().includes(query_lower) || (viz.description && viz.description.toLowerCase().includes(query_lower)))) { score += 1; reasons.push("可视化标题或描述"); } return { score, reasons }; }