mirror of
https://github.com/chartdb/chartdb.git
synced 2025-11-03 13:33:25 +00:00
fix(AI exports): add cahching layer to SQL exports (#390)
* fix(AI exports): add cahching layer to SQL exports * remove logs --------- Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
This commit is contained in:
27
src/lib/data/export-metadata/export-sql-cache.ts
Normal file
27
src/lib/data/export-metadata/export-sql-cache.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import type { DatabaseType } from '@/lib/domain/database-type';
|
||||||
|
import { sha256 } from '@/lib/utils';
|
||||||
|
|
||||||
|
export const getFromCache = (key: string): string | null => {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(`sql-export-${key}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to read from localStorage:', e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setInCache = (key: string, value: string): void => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(`sql-export-${key}`, value);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to write to localStorage:', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateCacheKey = async (
|
||||||
|
databaseType: DatabaseType,
|
||||||
|
sqlScript: string
|
||||||
|
): Promise<string> => {
|
||||||
|
const rawKey = `${databaseType}:${sqlScript}`;
|
||||||
|
return await sha256(rawKey);
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import { OPENAI_API_KEY } from '@/lib/env';
|
|||||||
import type { DatabaseType } from '@/lib/domain/database-type';
|
import type { DatabaseType } from '@/lib/domain/database-type';
|
||||||
import type { DBTable } from '@/lib/domain/db-table';
|
import type { DBTable } from '@/lib/domain/db-table';
|
||||||
import type { DataType } from '../data-types/data-types';
|
import type { DataType } from '../data-types/data-types';
|
||||||
|
import { generateCacheKey, getFromCache, setInCache } from './export-sql-cache';
|
||||||
|
|
||||||
export const exportBaseSQL = (diagram: Diagram): string => {
|
export const exportBaseSQL = (diagram: Diagram): string => {
|
||||||
const { tables, relationships } = diagram;
|
const { tables, relationships } = diagram;
|
||||||
@@ -197,18 +198,27 @@ export const exportSQL = async (
|
|||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
}
|
}
|
||||||
): Promise<string> => {
|
): Promise<string> => {
|
||||||
|
const sqlScript = exportBaseSQL(diagram);
|
||||||
|
const cacheKey = await generateCacheKey(databaseType, sqlScript);
|
||||||
|
|
||||||
|
const cachedResult = getFromCache(cacheKey);
|
||||||
|
if (cachedResult) {
|
||||||
|
return cachedResult;
|
||||||
|
}
|
||||||
|
|
||||||
const [{ streamText, generateText }, { createOpenAI }] = await Promise.all([
|
const [{ streamText, generateText }, { createOpenAI }] = await Promise.all([
|
||||||
import('ai'),
|
import('ai'),
|
||||||
import('@ai-sdk/openai'),
|
import('@ai-sdk/openai'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const openai = createOpenAI({
|
const openai = createOpenAI({
|
||||||
apiKey: OPENAI_API_KEY,
|
apiKey: OPENAI_API_KEY,
|
||||||
});
|
});
|
||||||
const sqlScript = exportBaseSQL(diagram);
|
|
||||||
const prompt = generateSQLPrompt(databaseType, sqlScript);
|
const prompt = generateSQLPrompt(databaseType, sqlScript);
|
||||||
|
|
||||||
if (options?.stream) {
|
if (options?.stream) {
|
||||||
const { textStream, text } = await streamText({
|
const { textStream, text: textPromise } = await streamText({
|
||||||
model: openai('gpt-4o-mini-2024-07-18'),
|
model: openai('gpt-4o-mini-2024-07-18'),
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
});
|
});
|
||||||
@@ -220,6 +230,9 @@ export const exportSQL = async (
|
|||||||
options.onResultStream(textPart);
|
options.onResultStream(textPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const text = await textPromise;
|
||||||
|
|
||||||
|
setInCache(cacheKey, text);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +241,7 @@ export const exportSQL = async (
|
|||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setInCache(cacheKey, text);
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -180,3 +180,16 @@ export const cloneDiagram = (
|
|||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const sha256 = async (message: string): Promise<string> => {
|
||||||
|
const msgBuffer = new TextEncoder().encode(message);
|
||||||
|
|
||||||
|
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
|
||||||
|
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
const hashHex = hashArray
|
||||||
|
.map((b) => b.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
return hashHex;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user