-feat 修复json格式问题
This commit is contained in:
@@ -289,45 +289,47 @@ Output Requirements:
|
||||
// Here we choose to throw so fallback static text appears.
|
||||
throw error;
|
||||
}
|
||||
// Cache storage for daily insight
|
||||
let dailyInsightCache: {
|
||||
data: { spending: string; budget: string };
|
||||
timestamp: number;
|
||||
contentHash: string;
|
||||
} | null = null;
|
||||
}
|
||||
|
||||
export interface DailyInsightContext {
|
||||
todaySpend: number;
|
||||
yesterdaySpend: number;
|
||||
monthlyBudget: number;
|
||||
monthlySpent: number;
|
||||
monthProgress: number; // 0-1
|
||||
topCategory?: { name: string; amount: number };
|
||||
maxTransaction?: { note: string; amount: number };
|
||||
lastWeekSpend?: number;
|
||||
streakDays?: number;
|
||||
// Cache storage for daily insight
|
||||
let dailyInsightCache: {
|
||||
data: { spending: string; budget: string };
|
||||
timestamp: number;
|
||||
contentHash: string;
|
||||
} | null = null;
|
||||
|
||||
export interface DailyInsightContext {
|
||||
todaySpend: number;
|
||||
yesterdaySpend: number;
|
||||
monthlyBudget: number;
|
||||
monthlySpent: number;
|
||||
monthProgress: number; // 0-1
|
||||
topCategory?: { name: string; amount: number };
|
||||
maxTransaction?: { note: string; amount: number };
|
||||
lastWeekSpend?: number;
|
||||
streakDays?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AI-powered daily insight
|
||||
*/
|
||||
export async function getDailyInsight(context: DailyInsightContext): Promise<{ spending: string; budget: string }> {
|
||||
// Hash needs to include new fields
|
||||
const currentHash = JSON.stringify(context);
|
||||
const NOW = Date.now();
|
||||
const CACHE_TTL = 30 * 60 * 1000; // 30 Minutes
|
||||
|
||||
// 1. Check Cache
|
||||
if (dailyInsightCache &&
|
||||
(NOW - dailyInsightCache.timestamp < CACHE_TTL) &&
|
||||
dailyInsightCache.contentHash === currentHash) {
|
||||
return dailyInsightCache.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AI-powered daily insight
|
||||
*/
|
||||
export async function getDailyInsight(context: DailyInsightContext): Promise<{ spending: string; budget: string }> {
|
||||
// Hash needs to include new fields
|
||||
const currentHash = JSON.stringify(context);
|
||||
const NOW = Date.now();
|
||||
const CACHE_TTL = 30 * 60 * 1000; // 30 Minutes
|
||||
const weekday = new Date().toLocaleDateString('zh-CN', { weekday: 'long' });
|
||||
const weekDiff = context.lastWeekSpend !== undefined ? (context.todaySpend - context.lastWeekSpend) : 0;
|
||||
|
||||
// 1. Check Cache
|
||||
if (dailyInsightCache &&
|
||||
(NOW - dailyInsightCache.timestamp < CACHE_TTL) &&
|
||||
dailyInsightCache.contentHash === currentHash) {
|
||||
return dailyInsightCache.data;
|
||||
}
|
||||
|
||||
const weekday = new Date().toLocaleDateString('zh-CN', { weekday: 'long' });
|
||||
const weekDiff = context.lastWeekSpend !== undefined ? (context.todaySpend - context.lastWeekSpend) : 0;
|
||||
|
||||
const prompt = `System: 你是 Novault 首席财务AI,也是用户的贴身管家。你的点评需要非常有温度、有依据。
|
||||
const prompt = `System: 你是 Novault 首席财务AI,也是用户的贴身管家。你的点评需要非常有温度、有依据。
|
||||
Context:
|
||||
- 今天是: ${weekday}
|
||||
- 连续记账: ${context.streakDays || 0} 天
|
||||
@@ -351,63 +353,64 @@ Task:
|
||||
- 结合月度进度,给出具体行动指南。
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await sendChatMessage(prompt);
|
||||
try {
|
||||
const response = await sendChatMessage(prompt);
|
||||
|
||||
if (response.message) {
|
||||
let content = response.message.trim();
|
||||
if (response.message) {
|
||||
let content = response.message.trim();
|
||||
|
||||
// Extract JSON object using regex to handle potential markdown or extra text
|
||||
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
||||
if (jsonMatch) {
|
||||
content = jsonMatch[0];
|
||||
} else {
|
||||
// Fallback cleanup if regex fails but it might still be JSON-ish
|
||||
content = content.replace(/^```json\s*/, '').replace(/\s*```$/, '');
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(content);
|
||||
} catch (e) {
|
||||
console.warn('AI returned invalid JSON, falling back to raw text split or default', content);
|
||||
// Fallback: simple split if possible or default
|
||||
parsed = {
|
||||
spending: content.slice(0, 50) + '...',
|
||||
budget: 'AI 分析数据格式异常,请稍后再试。'
|
||||
};
|
||||
}
|
||||
|
||||
const result = {
|
||||
spending: parsed.spending || '暂无点评',
|
||||
budget: parsed.budget || '暂无建议'
|
||||
};
|
||||
|
||||
// Update Cache
|
||||
dailyInsightCache = {
|
||||
data: result,
|
||||
timestamp: NOW,
|
||||
contentHash: currentHash
|
||||
};
|
||||
|
||||
return result;
|
||||
// Extract JSON object using regex to handle potential markdown or extra text
|
||||
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
||||
if (jsonMatch) {
|
||||
content = jsonMatch[0];
|
||||
} else {
|
||||
// Fallback cleanup if regex fails but it might still be JSON-ish
|
||||
content = content.replace(/^```json\s*/, '').replace(/\s*```$/, '');
|
||||
}
|
||||
throw new Error('No insight received');
|
||||
} catch (error) {
|
||||
console.error('Failed to get AI insight:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getSessionId,
|
||||
clearSession,
|
||||
sendChatMessage,
|
||||
transcribeAudio,
|
||||
confirmTransaction,
|
||||
cancelSession,
|
||||
processVoiceInput,
|
||||
isConfirmationCardComplete,
|
||||
formatConfirmationCard,
|
||||
getFinancialAdvice,
|
||||
};
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(content);
|
||||
} catch (e) {
|
||||
console.warn('AI returned invalid JSON, falling back to raw text split or default', content);
|
||||
// Fallback: simple split if possible or default
|
||||
parsed = {
|
||||
spending: content.slice(0, 50) + '...',
|
||||
budget: 'AI 分析数据格式异常,请稍后再试。'
|
||||
};
|
||||
}
|
||||
|
||||
const result = {
|
||||
spending: parsed.spending || '暂无点评',
|
||||
budget: parsed.budget || '暂无建议'
|
||||
};
|
||||
|
||||
// Update Cache
|
||||
dailyInsightCache = {
|
||||
data: result,
|
||||
timestamp: NOW,
|
||||
contentHash: currentHash
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
throw new Error('No insight received');
|
||||
} catch (error) {
|
||||
console.error('Failed to get AI insight:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getSessionId,
|
||||
clearSession,
|
||||
sendChatMessage,
|
||||
transcribeAudio,
|
||||
confirmTransaction,
|
||||
cancelSession,
|
||||
processVoiceInput,
|
||||
isConfirmationCardComplete,
|
||||
formatConfirmationCard,
|
||||
getFinancialAdvice,
|
||||
getDailyInsight,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user