Download server/cacheManager.js from rxb0506/lifekline: direct link, hf CLI and curl.
- Browser
- Download file 10.3 kB
-
https://huggingface.co/spaces/rxb0506/lifekline/resolve/main/server/cacheManager.js
- Command line
-
hf download hf://spaces/rxb0506/lifekline/server/cacheManager.js
-
curl -L -o cacheManager.js https://huggingface.co/spaces/rxb0506/lifekline/resolve/main/server/cacheManager.js
10.3 kB
| /** | |
| * 八字分析缓存管理器 | |
| * 实现永久缓存策略,同一八字返回相同核心结论 | |
| */ | |
| import crypto from 'crypto'; | |
| import { getDb, nowIso } from './database.js'; | |
| /** | |
| * 计算八字哈希值 | |
| * @param {string} yearPillar - 年柱 | |
| * @param {string} monthPillar - 月柱 | |
| * @param {string} dayPillar - 日柱 | |
| * @param {string} hourPillar - 时柱 | |
| * @returns {string} 16位哈希值 | |
| */ | |
| export const computeBaziHash = (yearPillar, monthPillar, dayPillar, hourPillar) => { | |
| const combined = `${yearPillar}|${monthPillar}|${dayPillar}|${hourPillar}`; | |
| return crypto.createHash('sha256').update(combined).digest('hex').substring(0, 16); | |
| }; | |
| /** | |
| * 获取缓存的核心分析结果 | |
| * @param {string} baziHash - 八字哈希 | |
| * @param {string} gender - 性别 (male/female) | |
| * @returns {object|null} 缓存的分析结果或null | |
| */ | |
| export const getCachedAnalysis = (baziHash, gender) => { | |
| const db = getDb(); | |
| const stmt = db.prepare(` | |
| SELECT * FROM bazi_analysis_cache | |
| WHERE bazi_hash = ? AND gender = ? | |
| `); | |
| const row = stmt.get(baziHash, gender); | |
| if (!row) return null; | |
| return { | |
| id: row.id, | |
| baziHash: row.bazi_hash, | |
| gender: row.gender, | |
| // 结构数据 | |
| structuralData: JSON.parse(row.structural_data || '{}'), | |
| // 命理骨架 | |
| personalityCore: JSON.parse(row.personality_core || '{}'), | |
| careerCore: JSON.parse(row.career_core || '{}'), | |
| wealthCore: JSON.parse(row.wealth_core || '{}'), | |
| marriageCore: JSON.parse(row.marriage_core || '{}'), | |
| healthCore: JSON.parse(row.health_core || '{}'), | |
| // K线数据 | |
| klineData: JSON.parse(row.kline_data || '[]'), | |
| peakYears: JSON.parse(row.peak_years || '[]'), | |
| troughYears: JSON.parse(row.trough_years || '[]'), | |
| // 新增分析维度 | |
| cryptoCore: JSON.parse(row.crypto_core || '{}'), | |
| monthlyFortune: JSON.parse(row.monthly_fortune || '{}'), | |
| yearlyFortune: JSON.parse(row.yearly_fortune || '{}'), | |
| luckyElements: JSON.parse(row.lucky_elements || '{}'), | |
| physicalTraits: JSON.parse(row.physical_traits || '{}'), | |
| keyDates: JSON.parse(row.key_dates || '{}'), | |
| pastEvents: JSON.parse(row.past_events || '[]'), | |
| futureEvents: JSON.parse(row.future_events || '[]'), | |
| // 元数据 | |
| modelUsed: row.model_used, | |
| version: row.version, | |
| createdAt: row.created_at, | |
| }; | |
| }; | |
| /** | |
| * 保存分析结果到缓存 | |
| * @param {object} data - 分析数据 | |
| */ | |
| export const cacheAnalysis = (data) => { | |
| const db = getDb(); | |
| const id = `cache_${data.baziHash}_${data.gender}_${Date.now()}`; | |
| const stmt = db.prepare(` | |
| INSERT OR REPLACE INTO bazi_analysis_cache ( | |
| id, bazi_hash, gender, | |
| structural_data, personality_core, career_core, wealth_core, | |
| marriage_core, health_core, kline_data, peak_years, trough_years, | |
| crypto_core, monthly_fortune, yearly_fortune, lucky_elements, | |
| physical_traits, key_dates, past_events, future_events, | |
| model_used, version, created_at | |
| ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) | |
| `); | |
| stmt.run( | |
| id, | |
| data.baziHash, | |
| data.gender, | |
| JSON.stringify(data.structuralData || {}), | |
| JSON.stringify(data.personalityCore || {}), | |
| JSON.stringify(data.careerCore || {}), | |
| JSON.stringify(data.wealthCore || {}), | |
| JSON.stringify(data.marriageCore || {}), | |
| JSON.stringify(data.healthCore || {}), | |
| JSON.stringify(data.klineData || []), | |
| JSON.stringify(data.peakYears || []), | |
| JSON.stringify(data.troughYears || []), | |
| JSON.stringify(data.cryptoCore || {}), | |
| JSON.stringify(data.monthlyFortune || {}), | |
| JSON.stringify(data.yearlyFortune || {}), | |
| JSON.stringify(data.luckyElements || {}), | |
| JSON.stringify(data.physicalTraits || {}), | |
| JSON.stringify(data.keyDates || {}), | |
| JSON.stringify(data.pastEvents || []), | |
| JSON.stringify(data.futureEvents || []), | |
| data.modelUsed || 'unknown', | |
| data.version || 1, | |
| nowIso() | |
| ); | |
| return id; | |
| }; | |
| /** | |
| * 从完整分析结果中提取核心数据用于缓存 | |
| * @param {object} analysisResult - AI返回的完整分析结果 | |
| * @param {object} chartData - K线数据 | |
| * @returns {object} 核心缓存数据 | |
| */ | |
| export const extractCoreData = (analysisResult, chartData) => { | |
| // 找出巅峰年和低谷年 | |
| const sortedByScore = [...(chartData || [])].sort((a, b) => b.score - a.score); | |
| const peakYears = sortedByScore.slice(0, 5).map(p => ({ year: p.year, age: p.age, score: p.score })); | |
| const troughYears = sortedByScore.slice(-5).reverse().map(p => ({ year: p.year, age: p.age, score: p.score })); | |
| return { | |
| structuralData: { | |
| bazi: analysisResult.bazi, | |
| summaryScore: analysisResult.summaryScore, | |
| }, | |
| personalityCore: { | |
| content: analysisResult.personality, | |
| score: analysisResult.personalityScore, | |
| }, | |
| careerCore: { | |
| content: analysisResult.industry, | |
| score: analysisResult.industryScore, | |
| }, | |
| wealthCore: { | |
| content: analysisResult.wealth, | |
| score: analysisResult.wealthScore, | |
| }, | |
| marriageCore: { | |
| content: analysisResult.marriage, | |
| score: analysisResult.marriageScore, | |
| }, | |
| healthCore: { | |
| content: analysisResult.health, | |
| score: analysisResult.healthScore, | |
| bodyParts: analysisResult.healthBodyParts || [], | |
| }, | |
| klineData: chartData, | |
| peakYears, | |
| troughYears, | |
| cryptoCore: { | |
| content: analysisResult.crypto, | |
| score: analysisResult.cryptoScore, | |
| cryptoYear: analysisResult.cryptoYear, | |
| cryptoStyle: analysisResult.cryptoStyle, | |
| }, | |
| monthlyFortune: { | |
| content: analysisResult.monthlyFortune, | |
| highlights: analysisResult.monthlyHighlights || [], | |
| }, | |
| yearlyFortune: { | |
| content: analysisResult.yearlyFortune, | |
| keyEvents: analysisResult.yearlyKeyEvents || [], | |
| }, | |
| luckyElements: { | |
| colors: analysisResult.luckyColors || [], | |
| directions: analysisResult.luckyDirections || [], | |
| zodiac: analysisResult.luckyZodiac || [], | |
| numbers: analysisResult.luckyNumbers || [], | |
| }, | |
| physicalTraits: { | |
| appearance: analysisResult.appearance, | |
| bodyType: analysisResult.bodyType, | |
| skin: analysisResult.skin, | |
| characterSummary: analysisResult.characterSummary, | |
| }, | |
| keyDates: { | |
| thisYear: analysisResult.keyDatesThisYear || [], | |
| thisMonth: analysisResult.keyDatesThisMonth || [], | |
| }, | |
| pastEvents: analysisResult.pastEvents || [], | |
| futureEvents: analysisResult.futureEvents || [], | |
| }; | |
| }; | |
| /** | |
| * 合并缓存数据和新生成的润色文字 | |
| * @param {object} cachedData - 缓存的核心数据 | |
| * @param {object} freshPolish - 新生成的文字润色(可选) | |
| * @returns {object} 最终分析结果 | |
| */ | |
| export const mergeCachedWithFresh = (cachedData, freshPolish = null) => { | |
| // 如果没有新润色,直接返回缓存数据构建的结果 | |
| const result = { | |
| bazi: cachedData.structuralData?.bazi || [], | |
| summary: freshPolish?.summary || cachedData.structuralData?.summary || '命理分析已从缓存加载', | |
| summaryScore: cachedData.structuralData?.summaryScore || 5, | |
| personality: cachedData.personalityCore?.content || '', | |
| personalityScore: cachedData.personalityCore?.score || 5, | |
| industry: cachedData.careerCore?.content || '', | |
| industryScore: cachedData.careerCore?.score || 5, | |
| wealth: cachedData.wealthCore?.content || '', | |
| wealthScore: cachedData.wealthCore?.score || 5, | |
| marriage: cachedData.marriageCore?.content || '', | |
| marriageScore: cachedData.marriageCore?.score || 5, | |
| health: cachedData.healthCore?.content || '', | |
| healthScore: cachedData.healthCore?.score || 5, | |
| healthBodyParts: cachedData.healthCore?.bodyParts || [], | |
| family: freshPolish?.family || cachedData.familyCore?.content || '', | |
| familyScore: cachedData.familyCore?.score || 5, | |
| fengShui: freshPolish?.fengShui || cachedData.fengShuiCore?.content || '', | |
| fengShuiScore: cachedData.fengShuiCore?.score || 5, | |
| crypto: cachedData.cryptoCore?.content || '', | |
| cryptoScore: cachedData.cryptoCore?.score || 5, | |
| cryptoYear: cachedData.cryptoCore?.cryptoYear || '待定', | |
| cryptoStyle: cachedData.cryptoCore?.cryptoStyle || '现货定投', | |
| // 新增字段 | |
| monthlyFortune: cachedData.monthlyFortune?.content || '', | |
| monthlyHighlights: cachedData.monthlyFortune?.highlights || [], | |
| yearlyFortune: cachedData.yearlyFortune?.content || '', | |
| yearlyKeyEvents: cachedData.yearlyFortune?.keyEvents || [], | |
| luckyColors: cachedData.luckyElements?.colors || [], | |
| luckyDirections: cachedData.luckyElements?.directions || [], | |
| luckyZodiac: cachedData.luckyElements?.zodiac || [], | |
| luckyNumbers: cachedData.luckyElements?.numbers || [], | |
| appearance: cachedData.physicalTraits?.appearance || '', | |
| bodyType: cachedData.physicalTraits?.bodyType || '', | |
| skin: cachedData.physicalTraits?.skin || '', | |
| characterSummary: cachedData.physicalTraits?.characterSummary || '', | |
| keyDatesThisYear: cachedData.keyDates?.thisYear || [], | |
| keyDatesThisMonth: cachedData.keyDates?.thisMonth || [], | |
| pastEvents: cachedData.pastEvents || [], | |
| futureEvents: cachedData.futureEvents || [], | |
| peakYears: cachedData.peakYears || [], | |
| troughYears: cachedData.troughYears || [], | |
| }; | |
| return result; | |
| }; | |
| /** | |
| * 检查缓存是否存在 | |
| * @param {string} baziHash - 八字哈希 | |
| * @param {string} gender - 性别 | |
| * @returns {boolean} | |
| */ | |
| export const hasCachedAnalysis = (baziHash, gender) => { | |
| const db = getDb(); | |
| const stmt = db.prepare(` | |
| SELECT COUNT(*) as count FROM bazi_analysis_cache | |
| WHERE bazi_hash = ? AND gender = ? | |
| `); | |
| const row = stmt.get(baziHash, gender); | |
| return row.count > 0; | |
| }; | |
| /** | |
| * 获取缓存统计信息 | |
| * @returns {object} 缓存统计 | |
| */ | |
| export const getCacheStats = () => { | |
| const db = getDb(); | |
| const totalStmt = db.prepare('SELECT COUNT(*) as count FROM bazi_analysis_cache'); | |
| const total = totalStmt.get().count; | |
| const recentStmt = db.prepare(` | |
| SELECT COUNT(*) as count FROM bazi_analysis_cache | |
| WHERE created_at > datetime('now', '-24 hours') | |
| `); | |
| const recent = recentStmt.get().count; | |
| return { total, recentlyAdded: recent }; | |
| }; | |
| export default { | |
| computeBaziHash, | |
| getCachedAnalysis, | |
| cacheAnalysis, | |
| extractCoreData, | |
| mergeCachedWithFresh, | |
| hasCachedAnalysis, | |
| getCacheStats, | |
| }; | |