From 935fea0bc10ea3071640c62b5e0311c166541d8a Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Fri, 28 Mar 2025 15:59:21 +0800 Subject: [PATCH] feat(drizzle-duckdb-wasm): memory decay demo --- .../playground/src/App.vue | 7 + .../playground/src/components/Checkbox.vue | 48 ++ .../components/Memory/DecayModelSettings.vue | 193 ++++++ .../components/Memory/DecayTimeSettings.vue | 224 +++++++ .../src/components/Memory/RecordDetail.vue | 192 ++++++ .../src/components/Memory/VisualizeChart.vue | 581 ++++++++++++++++++ .../src/components/Memory/VisualizeTable.vue | 177 ++++++ .../playground/src/components/Range.vue | 330 ++++++++++ .../playground/src/composables/memory/db.ts | 115 ++++ .../playground/src/main.ts | 1 + .../playground/src/pages/graph.vue | 6 +- .../playground/src/pages/memory-decay.vue | 351 +++++++++++ .../playground/src/styles/themes.css | 14 + .../src/components/Form/Range/Range.vue | 68 +- 14 files changed, 2270 insertions(+), 37 deletions(-) create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Checkbox.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayModelSettings.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayTimeSettings.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Memory/RecordDetail.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeChart.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeTable.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/components/Range.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/composables/memory/db.ts create mode 100644 packages/drizzle-duckdb-wasm/playground/src/pages/memory-decay.vue create mode 100644 packages/drizzle-duckdb-wasm/playground/src/styles/themes.css diff --git a/packages/drizzle-duckdb-wasm/playground/src/App.vue b/packages/drizzle-duckdb-wasm/playground/src/App.vue index 38483ca9d..8351506db 100644 --- a/packages/drizzle-duckdb-wasm/playground/src/App.vue +++ b/packages/drizzle-duckdb-wasm/playground/src/App.vue @@ -39,6 +39,13 @@ const toggleDark = useToggle(isDark) >

Graph

+
+ +

Memory Decay

+
diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Checkbox.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Checkbox.vue new file mode 100644 index 000000000..9b7971946 --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Checkbox.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayModelSettings.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayModelSettings.vue new file mode 100644 index 000000000..6d52ad6ff --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayModelSettings.vue @@ -0,0 +1,193 @@ + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayTimeSettings.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayTimeSettings.vue new file mode 100644 index 000000000..ed0d415b3 --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/DecayTimeSettings.vue @@ -0,0 +1,224 @@ + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Memory/RecordDetail.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/RecordDetail.vue new file mode 100644 index 000000000..d3ab7ed24 --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/RecordDetail.vue @@ -0,0 +1,192 @@ + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeChart.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeChart.vue new file mode 100644 index 000000000..c6042d50e --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeChart.vue @@ -0,0 +1,581 @@ + + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeTable.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeTable.vue new file mode 100644 index 000000000..d355ef58d --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Memory/VisualizeTable.vue @@ -0,0 +1,177 @@ + + + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/components/Range.vue b/packages/drizzle-duckdb-wasm/playground/src/components/Range.vue new file mode 100644 index 000000000..4cca8005a --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/components/Range.vue @@ -0,0 +1,330 @@ + + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/composables/memory/db.ts b/packages/drizzle-duckdb-wasm/playground/src/composables/memory/db.ts new file mode 100644 index 000000000..fe40b93c5 --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/composables/memory/db.ts @@ -0,0 +1,115 @@ +import { buildDSN } from '../../../../src/dsn' +import { drizzle } from '../../../../src/index' +import * as schema from '../../../db/schema' + +export async function connectToDatabase() { + return drizzle(buildDSN({ + scheme: 'duckdb-wasm:', + bundles: 'import-url', + logger: true, + }), { schema }) +} + +export async function createSchema(db) { + await db.execute(` + CREATE TABLE IF NOT EXISTS currentscores ( + storyid VARCHAR, + score DOUBLE, + lastupdate TIMESTAMP, + last_retrieved_at TIMESTAMP, + retrieval_count INTEGER DEFAULT 0 + ) + `) +} + +export async function loadSampleData(db) { + const now = new Date() + const sampleData = [] + + for (let i = 1; i <= 20; i++) { + const daysAgo = Math.random() * 60 + const lastUpdate = new Date(now.getTime() - (daysAgo * 24 * 60 * 60 * 1000)) + const retrievalCount = Math.floor(Math.random() * 10) + let retrievalDaysAgo = retrievalCount > 0 ? Math.random() * daysAgo * (1 - retrievalCount / 15) : daysAgo + retrievalDaysAgo = Math.max(0, retrievalDaysAgo) + const lastRetrievedAt = new Date(now.getTime() - (retrievalDaysAgo * 24 * 60 * 60 * 1000)) + const score = Math.floor(Math.random() * 900) + 100 + + sampleData.push({ + storyid: `story-${i}`, + score, + lastupdate: lastUpdate.toISOString(), + last_retrieved_at: lastRetrievedAt.toISOString(), + retrieval_count: retrievalCount, + }) + } + + for (const item of sampleData) { + await db.execute(` + INSERT INTO currentscores (storyid, score, lastupdate, last_retrieved_at, retrieval_count) + VALUES ('${item.storyid}', ${item.score}, '${item.lastupdate}', '${item.last_retrieved_at}', ${item.retrieval_count}) + `) + } +} + +export async function generateDecayQuery(db, { + simulatedTimeOffset, + decayRate, + timeUnitInSeconds, + longTermMemoryEnabled, + longTermMemoryThreshold, + longTermMemoryStability, + retrievalBoost, + retrievalDecaySlowdown, +}) { + const simulatedTimestamp = `(CAST(now() AS TIMESTAMP) + INTERVAL '${simulatedTimeOffset} seconds')` + + const ltmFactorClause = longTermMemoryEnabled + ? ` + CASE + WHEN retrieval_count >= ${longTermMemoryThreshold} + THEN 1.0 - ((${longTermMemoryStability}) ^ (retrieval_count / ${longTermMemoryThreshold})) + ELSE 0 + END AS ltm_factor, + ` + : '' + + const ltmDecayModifier = longTermMemoryEnabled + ? `* (1 - ltm_factor)` + : '' + + const query = ` + SELECT + storyid, + score, + lastupdate, + last_retrieved_at, + retrieval_count, + CAST(lastupdate AS VARCHAR) as lastupdate_str, + CAST(last_retrieved_at AS VARCHAR) as last_retrieved_str, + (EXTRACT(EPOCH FROM (${simulatedTimestamp} - lastupdate))) as age_in_seconds, + (EXTRACT(EPOCH FROM (${simulatedTimestamp} - last_retrieved_at))) as time_since_retrieval, + ${ltmFactorClause} + score * + exp(-${decayRate} * (EXTRACT(EPOCH FROM (${simulatedTimestamp} - lastupdate)))/(${timeUnitInSeconds}) ${ltmDecayModifier}) * + (1 + (retrieval_count * ${retrievalBoost} * + exp(-${decayRate * retrievalDecaySlowdown} * + (EXTRACT(EPOCH FROM (${simulatedTimestamp} - last_retrieved_at)))/(${timeUnitInSeconds})))) + as decayed_score + FROM currentscores + ORDER BY decayed_score DESC + ` + + return query +} + +export async function simulateRetrieval(db, storyId, simulatedTime) { + const simulatedTimestamp = simulatedTime.toISOString() + + await db.execute(` + UPDATE currentscores + SET last_retrieved_at = '${simulatedTimestamp}', + retrieval_count = retrieval_count + 1 + WHERE storyid = '${storyId}' + `) +} diff --git a/packages/drizzle-duckdb-wasm/playground/src/main.ts b/packages/drizzle-duckdb-wasm/playground/src/main.ts index 52e83a7af..0bc7c48da 100644 --- a/packages/drizzle-duckdb-wasm/playground/src/main.ts +++ b/packages/drizzle-duckdb-wasm/playground/src/main.ts @@ -5,6 +5,7 @@ import { routes } from 'vue-router/auto-routes' import App from './App.vue' import '@unocss/reset/tailwind.css' import 'uno.css' +import './styles/themes.css' const router = createRouter({ routes, history: createWebHashHistory() }) diff --git a/packages/drizzle-duckdb-wasm/playground/src/pages/graph.vue b/packages/drizzle-duckdb-wasm/playground/src/pages/graph.vue index e793bd48f..36c2501be 100644 --- a/packages/drizzle-duckdb-wasm/playground/src/pages/graph.vue +++ b/packages/drizzle-duckdb-wasm/playground/src/pages/graph.vue @@ -728,7 +728,7 @@ onUnmounted(() => {
- @@ -743,7 +743,7 @@ onUnmounted(() => {
- @@ -752,7 +752,7 @@ onUnmounted(() => {
- diff --git a/packages/drizzle-duckdb-wasm/playground/src/pages/memory-decay.vue b/packages/drizzle-duckdb-wasm/playground/src/pages/memory-decay.vue new file mode 100644 index 000000000..40474a0af --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/pages/memory-decay.vue @@ -0,0 +1,351 @@ + + + + diff --git a/packages/drizzle-duckdb-wasm/playground/src/styles/themes.css b/packages/drizzle-duckdb-wasm/playground/src/styles/themes.css new file mode 100644 index 000000000..8281fe100 --- /dev/null +++ b/packages/drizzle-duckdb-wasm/playground/src/styles/themes.css @@ -0,0 +1,14 @@ +:root { + --theme-colors-hue: 255; + --theme-colors-chroma: calc(0.18 + (cos(var(--theme-colors-hue) * 3.14159265 / 180) * 0.04)); + --theme-colors-chroma-50: calc(var(--theme-colors-chroma) * 0.3); + --theme-colors-chroma-100: calc(var(--theme-colors-chroma) * 0.5); + --theme-colors-chroma-200: calc(var(--theme-colors-chroma) * 0.6); + --theme-colors-chroma-300: calc(var(--theme-colors-chroma) * 0.75); + --theme-colors-chroma-400: var(--theme-colors-chroma); + --theme-colors-chroma-600: calc(var(--theme-colors-chroma) * 1.15); + --theme-colors-chroma-700: calc(var(--theme-colors-chroma) * 1.1); + --theme-colors-chroma-800: calc(var(--theme-colors-chroma) * 0.85); + --theme-colors-chroma-900: calc(var(--theme-colors-chroma) * 0.7); + --theme-colors-chroma-950: calc(var(--theme-colors-chroma) * 0.5); +} diff --git a/packages/stage-ui/src/components/Form/Range/Range.vue b/packages/stage-ui/src/components/Form/Range/Range.vue index 9e83c8514..111cfd698 100644 --- a/packages/stage-ui/src/components/Form/Range/Range.vue +++ b/packages/stage-ui/src/components/Form/Range/Range.vue @@ -58,7 +58,7 @@ function updateTrackColor() { :min="scaledMin" :max="scaledMax" :step="scaledStep" - class="data-gui-range slider-progress" + class="form_input-range slider-progress" @input="(e) => { (e.target as HTMLInputElement).style.setProperty('--value', (e.target as HTMLInputElement).value) }" @@ -68,7 +68,7 @@ function updateTrackColor() {