answer-book-mcp
Version:
智能问答和决策辅助的 MCP (Model Context Protocol) 服务器
766 lines (673 loc) • 22.4 kB
JavaScript
/**
* 决策建议工具
* 根据用户描述的情况提供个性化的决策建议
*/
import { BaseTool } from './base-tool.js'
import { validateGetAdvice } from '../utils/validator.js'
import { logger } from '../utils/logger.js'
/**
* 决策建议工具类
*/
export class GetAdviceTool extends BaseTool {
constructor(storageManager, config) {
super(
'get_advice',
'根据您描述的情况和选项,提供个性化的决策建议和分析',
{
type: 'object',
properties: {
situation: {
type: 'string',
description: '详细描述您面临的情况或困境',
minLength: 10,
maxLength: 2000
},
options: {
type: 'array',
description: '可选的决策选项(可选)',
items: {
type: 'string',
maxLength: 200
},
maxItems: 10
},
priority: {
type: 'string',
description: '决策优先级倾向',
enum: ['practical', 'emotional', 'balanced', 'risk_averse', 'innovative'],
default: 'balanced'
},
timeline: {
type: 'string',
description: '决策时间紧迫性',
enum: ['urgent', 'normal', 'flexible']
}
},
required: ['situation']
}
)
this.storageManager = storageManager
this.config = config
// 决策框架模板
this.decisionFrameworks = {
practical: {
name: '实用主义框架',
factors: ['成本效益', '可行性', '资源需求', '实施难度', '短期收益'],
weight: { cost: 0.3, feasibility: 0.3, resources: 0.2, difficulty: 0.1, benefit: 0.1 }
},
emotional: {
name: '情感导向框架',
factors: ['个人感受', '价值观匹配', '内心声音', '情感满足', '人际关系'],
weight: { feeling: 0.3, values: 0.25, intuition: 0.2, satisfaction: 0.15, relationships: 0.1 }
},
balanced: {
name: '平衡决策框架',
factors: ['理性分析', '情感考量', '风险评估', '机会成本', '长期影响'],
weight: { rational: 0.25, emotional: 0.2, risk: 0.2, opportunity: 0.15, longterm: 0.2 }
},
risk_averse: {
name: '风险规避框架',
factors: ['安全性', '稳定性', '可预测性', '保障措施', '退路选择'],
weight: { safety: 0.3, stability: 0.25, predictability: 0.2, protection: 0.15, backup: 0.1 }
},
innovative: {
name: '创新导向框架',
factors: ['创新潜力', '学习机会', '突破可能', '未来趋势', '差异化优势'],
weight: { innovation: 0.3, learning: 0.2, breakthrough: 0.2, trend: 0.15, advantage: 0.15 }
}
}
this.storageManager = storageManager
this.config = config
// 时间紧迫性影响因子
this.timelineFactors = {
urgent: {
name: '紧急决策',
emphasis: ['快速执行', '现有资源', '简单方案', '风险控制'],
multiplier: { speed: 1.5, simplicity: 1.3, resources: 1.2, risk: 0.8 }
},
normal: {
name: '常规决策',
emphasis: ['全面分析', '多方考虑', '充分准备', '平衡选择'],
multiplier: { analysis: 1.2, consideration: 1.1, preparation: 1.1, balance: 1.0 }
},
flexible: {
name: '灵活决策',
emphasis: ['深度思考', '创新方案', '长远规划', '最优选择'],
multiplier: { thinking: 1.3, innovation: 1.4, planning: 1.3, optimization: 1.2 }
}
}
}
/**
* 参数验证
*/
async validateParams(params) {
const cleanParams = await super.validateParams(params)
return validateGetAdvice(cleanParams)
}
/**
* 执行决策建议逻辑
*/
async run(params) {
const {
situation,
options = [],
priority = 'balanced',
timeline
} = params
try {
logger.info('开始生成决策建议', {
situationLength: situation.length,
optionsCount: options.length,
priority,
timeline
})
// 分析情况
const situationAnalysis = await this.analyzeSituation(situation)
// 获取相关答案
const answers = await this.storageManager.loadAnswers()
const relevantAnswers = await this.findRelevantAnswers(situation, answers)
// 生成决策建议
const advice = await this.generateAdvice({
situation,
situationAnalysis,
options,
priority,
timeline,
relevantAnswers
})
// 保存到历史记录
await this.saveAdviceToHistory({
situation,
advice,
priority,
timeline,
options
})
logger.info('决策建议生成完成', {
adviceType: advice.type,
optionsAnalyzed: advice.options_analysis?.length || 0
})
return this.createSuccessResponse(advice, '已为您生成决策建议')
} catch (error) {
logger.error('生成决策建议失败', {
error: error.message,
situationLength: situation.length
})
throw error
}
}
/**
* 分析情况
*/
async analyzeSituation(situation) {
try {
const analysis = {
keywords: this.extractKeywords(situation),
sentiment: this.analyzeSentiment(situation),
complexity: this.assessComplexity(situation),
domain: await this.identifyDomain(situation),
urgency: this.assessUrgency(situation),
stakeholders: this.identifyStakeholders(situation),
constraints: this.identifyConstraints(situation)
}
return analysis
} catch (error) {
logger.warn('情况分析失败', { error: error.message })
return {
keywords: [],
sentiment: 'neutral',
complexity: 'medium',
domain: 'general',
urgency: 'normal',
stakeholders: [],
constraints: []
}
}
}
/**
* 提取关键词
*/
extractKeywords(text) {
const words = text.match(/[\u4e00-\u9fa5]+|[a-zA-Z]+/g) || []
const stopWords = new Set([
'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '上', '也', '很', '到', '说', '要', '去', '你', '会',
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were'
])
const keywordFreq = {}
words.forEach(word => {
const lowerWord = word.toLowerCase()
if (word.length > 1 && !stopWords.has(lowerWord)) {
keywordFreq[word] = (keywordFreq[word] || 0) + 1
}
})
return Object.entries(keywordFreq)
.sort(([,a], [,b]) => b - a)
.slice(0, 10)
.map(([word]) => word)
}
/**
* 情感分析
*/
analyzeSentiment(text) {
const positiveWords = ['好', '棒', '优秀', '成功', '快乐', '满意', '希望', '机会', 'good', 'great', 'excellent', 'success', 'happy', 'opportunity']
const negativeWords = ['坏', '糟糕', '失败', '困难', '问题', '担心', '焦虑', 'bad', 'terrible', 'failure', 'difficult', 'problem', 'worry', 'anxiety']
const textLower = text.toLowerCase()
let positiveScore = 0
let negativeScore = 0
positiveWords.forEach(word => {
if (textLower.includes(word)) positiveScore++
})
negativeWords.forEach(word => {
if (textLower.includes(word)) negativeScore++
})
if (positiveScore > negativeScore) return 'positive'
if (negativeScore > positiveScore) return 'negative'
return 'neutral'
}
/**
* 评估复杂度
*/
assessComplexity(situation) {
const length = situation.length
const sentences = situation.split(/[。!?.!?]/).length
const keywords = this.extractKeywords(situation).length
let score = 0
if (length > 500) score += 2
else if (length > 200) score += 1
if (sentences > 5) score += 2
else if (sentences > 3) score += 1
if (keywords > 8) score += 2
else if (keywords > 5) score += 1
if (score >= 4) return 'high'
if (score >= 2) return 'medium'
return 'low'
}
/**
* 识别领域
*/
async identifyDomain(situation) {
try {
const result = await this.server.matcher.suggestCategory(situation)
return result.category
} catch (error) {
return 'general'
}
}
/**
* 评估紧迫性
*/
assessUrgency(situation) {
const urgentKeywords = ['紧急', '急需', '马上', '立即', '尽快', 'urgent', 'immediately', 'asap', 'quickly']
const flexibleKeywords = ['考虑', '思考', '计划', '将来', '未来', 'consider', 'think', 'plan', 'future']
const textLower = situation.toLowerCase()
const urgentCount = urgentKeywords.filter(keyword => textLower.includes(keyword)).length
const flexibleCount = flexibleKeywords.filter(keyword => textLower.includes(keyword)).length
if (urgentCount > flexibleCount) return 'urgent'
if (flexibleCount > urgentCount) return 'flexible'
return 'normal'
}
/**
* 识别利益相关者
*/
identifyStakeholders(situation) {
const stakeholderPatterns = {
'家人': /家人|父母|配偶|孩子|家庭|family|parents|spouse|children/i,
'同事': /同事|同事|团队|老板|公司|colleague|team|boss|company/i,
'朋友': /朋友|朋友圈|社交|friend|social/i,
'客户': /客户|用户|顾客|client|customer|user/i,
'合作伙伴': /合作|伙伴|供应商|partner|supplier/i
}
const stakeholders = []
for (const [stakeholder, pattern] of Object.entries(stakeholderPatterns)) {
if (pattern.test(situation)) {
stakeholders.push(stakeholder)
}
}
return stakeholders
}
/**
* 识别约束条件
*/
identifyConstraints(situation) {
const constraintPatterns = {
'时间': /时间|期限|截止|deadline|time|schedule/i,
'预算': /预算|资金|成本|费用|budget|cost|money/i,
'资源': /资源|人力|设备|resource|manpower|equipment/i,
'技能': /技能|能力|经验|skill|ability|experience/i,
'政策': /政策|规定|法律|policy|regulation|law/i
}
const constraints = []
for (const [constraint, pattern] of Object.entries(constraintPatterns)) {
if (pattern.test(situation)) {
constraints.push(constraint)
}
}
return constraints
}
/**
* 查找相关答案
*/
async findRelevantAnswers(situation, answers) {
try {
const matchResult = await this.server.matcher.findBestAnswer(
situation,
answers,
{ category: 'decision' }
)
// 获取相关的决策类答案
const relevantAnswers = answers
.filter(answer =>
answer.category === 'decision' ||
answer.category === 'general'
)
.sort((a, b) => (b.success_rate || 0.5) - (a.success_rate || 0.5))
.slice(0, 5)
return relevantAnswers
} catch (error) {
logger.warn('查找相关答案失败', { error: error.message })
return []
}
}
/**
* 生成决策建议
*/
async generateAdvice(context) {
const {
situation,
situationAnalysis,
options,
priority,
timeline,
relevantAnswers
} = context
const framework = this.decisionFrameworks[priority]
const timelineFactor = timeline ? this.timelineFactors[timeline] : null
const advice = {
type: 'decision_advice',
situation_summary: this.summarizeSituation(situation, situationAnalysis),
framework_used: framework.name,
analysis: {
complexity: situationAnalysis.complexity,
domain: situationAnalysis.domain,
urgency: situationAnalysis.urgency,
key_factors: framework.factors,
stakeholders: situationAnalysis.stakeholders,
constraints: situationAnalysis.constraints
},
recommendations: [],
options_analysis: [],
action_plan: [],
considerations: [],
related_wisdom: []
}
// 生成主要建议
advice.recommendations = this.generateRecommendations(
situationAnalysis,
framework,
timelineFactor
)
// 分析选项(如果提供)
if (options.length > 0) {
advice.options_analysis = this.analyzeOptions(
options,
situationAnalysis,
framework
)
}
// 生成行动计划
advice.action_plan = this.generateActionPlan(
situationAnalysis,
timelineFactor
)
// 生成考虑要点
advice.considerations = this.generateConsiderations(
situationAnalysis,
framework
)
// 添加相关智慧
advice.related_wisdom = relevantAnswers.map(answer => ({
text: answer.text,
category: answer.category,
relevance: 'decision_support'
}))
return advice
}
/**
* 总结情况
*/
summarizeSituation(situation, analysis) {
const summary = {
main_issue: situation.substring(0, 100) + (situation.length > 100 ? '...' : ''),
complexity_level: analysis.complexity,
primary_domain: analysis.domain,
emotional_tone: analysis.sentiment,
time_sensitivity: analysis.urgency
}
return summary
}
/**
* 生成建议
*/
generateRecommendations(analysis, framework, timelineFactor) {
const recommendations = []
// 基于框架生成建议
if (framework.name === '实用主义框架') {
recommendations.push({
priority: 'high',
action: '进行成本效益分析',
reason: '实用主义决策需要明确的投入产出比',
timeline: timelineFactor?.name === '紧急决策' ? '立即执行' : '1-2天内完成'
})
recommendations.push({
priority: 'medium',
action: '评估可用资源',
reason: '确保有足够的资源支持决策实施',
timeline: '决策前完成'
})
} else if (framework.name === '情感导向框架') {
recommendations.push({
priority: 'high',
action: '倾听内心声音',
reason: '情感导向决策需要与个人价值观保持一致',
timeline: '充分思考后决定'
})
recommendations.push({
priority: 'medium',
action: '考虑对人际关系的影响',
reason: '情感决策往往涉及重要的人际关系',
timeline: '决策前评估'
})
} else if (framework.name === '平衡决策框架') {
recommendations.push({
priority: 'high',
action: '制作决策矩阵',
reason: '平衡决策需要系统性地权衡各个因素',
timeline: '决策前1-3天'
})
recommendations.push({
priority: 'medium',
action: '寻求多方意见',
reason: '平衡的决策需要多角度的输入',
timeline: '收集意见阶段'
})
}
// 基于复杂度调整建议
if (analysis.complexity === 'high') {
recommendations.push({
priority: 'high',
action: '分解复杂问题',
reason: '复杂情况需要分步骤处理',
timeline: '优先执行'
})
}
// 基于紧迫性调整建议
if (analysis.urgency === 'urgent') {
recommendations.unshift({
priority: 'critical',
action: '快速决策',
reason: '时间紧迫,需要基于现有信息快速决定',
timeline: '立即'
})
}
return recommendations.slice(0, 5) // 最多5个建议
}
/**
* 分析选项
*/
analyzeOptions(options, analysis, framework) {
return options.map((option, index) => {
const scores = {}
let totalScore = 0
// 基于框架因素评分
framework.factors.forEach(factor => {
const score = this.scoreOptionForFactor(option, factor, analysis)
scores[factor] = score
totalScore += score * (framework.weight[Object.keys(framework.weight)[framework.factors.indexOf(factor)]] || 0.2)
})
return {
option,
index: index + 1,
overall_score: Math.round(totalScore * 100) / 100,
factor_scores: scores,
pros: this.generatePros(option, analysis),
cons: this.generateCons(option, analysis),
recommendation: totalScore > 0.7 ? 'strongly_recommended' :
totalScore > 0.5 ? 'recommended' :
totalScore > 0.3 ? 'consider' : 'not_recommended'
}
})
}
/**
* 为特定因素评分选项
*/
scoreOptionForFactor(option, factor, analysis) {
// 简化的评分逻辑,实际项目中可以更复杂
const optionLower = option.toLowerCase()
const factorKeywords = {
'成本效益': ['便宜', '经济', '节省', 'cheap', 'economic', 'save'],
'可行性': ['可行', '容易', '简单', 'feasible', 'easy', 'simple'],
'个人感受': ['喜欢', '开心', '满意', 'like', 'happy', 'satisfied'],
'风险评估': ['安全', '稳定', '保险', 'safe', 'stable', 'secure'],
'创新潜力': ['新', '创新', '突破', 'new', 'innovative', 'breakthrough']
}
const keywords = factorKeywords[factor] || []
const matchCount = keywords.filter(keyword => optionLower.includes(keyword)).length
return Math.min(1.0, 0.3 + (matchCount * 0.2)) // 基础分0.3,每个匹配关键词+0.2
}
/**
* 生成优点
*/
generatePros(option, analysis) {
const pros = []
const optionLower = option.toLowerCase()
if (optionLower.includes('快') || optionLower.includes('quick')) {
pros.push('执行速度快')
}
if (optionLower.includes('便宜') || optionLower.includes('cheap')) {
pros.push('成本较低')
}
if (optionLower.includes('安全') || optionLower.includes('safe')) {
pros.push('风险较小')
}
// 如果没有明显优点,添加通用优点
if (pros.length === 0) {
pros.push('是一个可考虑的选择')
}
return pros
}
/**
* 生成缺点
*/
generateCons(option, analysis) {
const cons = []
const optionLower = option.toLowerCase()
if (optionLower.includes('贵') || optionLower.includes('expensive')) {
cons.push('成本较高')
}
if (optionLower.includes('难') || optionLower.includes('difficult')) {
cons.push('实施难度大')
}
if (optionLower.includes('险') || optionLower.includes('risk')) {
cons.push('存在一定风险')
}
// 如果没有明显缺点,添加通用提醒
if (cons.length === 0) {
cons.push('需要仔细评估具体细节')
}
return cons
}
/**
* 生成行动计划
*/
generateActionPlan(analysis, timelineFactor) {
const plan = []
if (timelineFactor?.name === '紧急决策') {
plan.push({
step: 1,
action: '收集关键信息',
timeline: '30分钟内',
description: '快速收集做决策所需的最关键信息'
})
plan.push({
step: 2,
action: '快速评估选项',
timeline: '1小时内',
description: '基于现有信息快速评估各个选项'
})
plan.push({
step: 3,
action: '做出决策',
timeline: '2小时内',
description: '基于评估结果做出最终决策'
})
} else {
plan.push({
step: 1,
action: '深入分析情况',
timeline: '1-2天',
description: '全面分析当前情况和各种因素'
})
plan.push({
step: 2,
action: '收集更多信息',
timeline: '2-3天',
description: '收集更多相关信息和他人意见'
})
plan.push({
step: 3,
action: '制定决策方案',
timeline: '3-5天',
description: '基于分析制定详细的决策方案'
})
plan.push({
step: 4,
action: '实施决策',
timeline: '1周内',
description: '开始实施选定的决策方案'
})
}
return plan
}
/**
* 生成考虑要点
*/
generateConsiderations(analysis, framework) {
const considerations = []
// 基于利益相关者
if (analysis.stakeholders.length > 0) {
considerations.push({
category: '利益相关者',
point: `考虑对${analysis.stakeholders.join('、')}的影响`,
importance: 'high'
})
}
// 基于约束条件
if (analysis.constraints.length > 0) {
considerations.push({
category: '约束条件',
point: `注意${analysis.constraints.join('、')}方面的限制`,
importance: 'high'
})
}
// 基于复杂度
if (analysis.complexity === 'high') {
considerations.push({
category: '复杂性管理',
point: '问题较为复杂,建议分步骤处理',
importance: 'medium'
})
}
// 基于情感倾向
if (analysis.sentiment === 'negative') {
considerations.push({
category: '情绪管理',
point: '当前可能存在负面情绪,建议冷静后再做决策',
importance: 'medium'
})
}
return considerations
}
/**
* 保存建议到历史记录
*/
async saveAdviceToHistory(data) {
try {
await this.storageManager.addHistoryRecord({
question: `决策咨询: ${data.situation.substring(0, 50)}...`,
answer: `建议类型: ${data.advice.type}`,
category: 'decision',
confidence: 0.8,
source: 'advice',
language: 'zh',
advice_data: {
priority: data.priority,
timeline: data.timeline,
options_count: data.options.length,
recommendations_count: data.advice.recommendations?.length || 0
}
})
} catch (error) {
logger.warn('保存建议历史失败', { error: error.message })
}
}
}