This commit is contained in:
yxshv 2024-04-14 14:32:12 +05:30
commit ac41d34771
21 changed files with 182 additions and 14 deletions

View file

@ -5,7 +5,8 @@
"scripts": {
"deploy": "wrangler deploy",
"dev": "wrangler dev",
"start": "wrangler dev"
"start": "wrangler dev",
"unsafe-reset-vector-db": "wrangler vectorize delete supermem-vector && wrangler vectorize create --dimensions=1536 supermem-vector-1 --metric=cosine"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240222.0",

View file

@ -5,6 +5,9 @@ import * as apiAsk from './routes/ask';
import * as apiChat from './routes/chat';
import * as apiBatchUploadTweets from './routes/batchUploadTweets';
import * as apiGetPageContent from './routes/getPageContent';
import * as apiDelete from './routes/delete';
import * as apiEdit from './routes/edit';
import * as apiWipeData from './routes/wipedata';
import { OpenAIEmbeddings } from './OpenAIEmbedder';
import { GenerativeModel } from '@google/generative-ai';
import { Request } from '@cloudflare/workers-types';
@ -30,7 +33,10 @@ routeMap.set('/chat', apiChat);
routeMap.set('/batchUploadTweets', apiBatchUploadTweets);
routeMap.set('/getPageContent', apiGetPageContent);
routeMap.set('/delete', apiDelete);
routeMap.set('/edit', apiEdit);
routeMap.set('/wipedata', apiWipeData);
// Add more route mappings as needed
// routeMap.set('/api/otherRoute', { ... });

View file

@ -17,6 +17,10 @@ export async function POST(request: Request, store: CloudflareVectorizeStore, _:
if (!body.pageContent || !body.url) {
return new Response(JSON.stringify({ message: 'Invalid Page Content' }), { status: 400 });
}
// TODO: FIX THIS,BUT TEMPERORILY TRIM page content to 1000 words
body.pageContent = body.pageContent.split(' ').slice(0, 1000).join(' ');
const newPageContent = `Title: ${body.title}\nDescription: ${body.description}\nURL: ${body.url}\nContent: ${body.pageContent}`;
const ourID = `${body.url}-${body.user}`;
@ -31,7 +35,7 @@ export async function POST(request: Request, store: CloudflareVectorizeStore, _:
{
pageContent: newPageContent,
metadata: {
title: body.title ?? '',
title: body.title?.slice(0, 50) ?? '',
description: body.description ?? '',
space: body.space ?? '',
url: body.url,

View file

@ -143,7 +143,7 @@ export async function POST(request: Request, _: CloudflareVectorizeStore, embedd
const ai = new Ai(env?.AI);
// @ts-ignore
const output: AiTextGenerationOutput = (await ai.run('@hf/mistralai/mistral-7b-instruct-v0.2', {
prompt,
prompt: prompt.slice(0, 6144),
stream: true,
})) as ReadableStream;

View file

@ -0,0 +1,27 @@
import { Request } from '@cloudflare/workers-types';
import { type CloudflareVectorizeStore } from '@langchain/cloudflare';
import { OpenAIEmbeddings } from '../OpenAIEmbedder';
import { GenerativeModel } from '@google/generative-ai';
import { seededRandom } from '../util';
export async function DELETE(request: Request, store: CloudflareVectorizeStore, _: OpenAIEmbeddings, m: GenerativeModel, env: Env) {
const { searchParams } = new URL(request.url);
const websiteUrl = searchParams.get('websiteUrl');
const user = searchParams.get('user');
if (!websiteUrl || !user) {
return new Response(JSON.stringify({ message: 'Invalid Request, need websiteUrl and user' }), { status: 400 });
}
const ourID = `${websiteUrl}-${user}`;
const uuid = await env.KV.get(ourID);
if (!uuid) {
return new Response(JSON.stringify({ message: 'Document not found' }), { status: 404 });
}
await store.delete({ ids: [uuid] });
return new Response(JSON.stringify({ message: 'Document deleted' }), { status: 200 });
}

View file

@ -0,0 +1,61 @@
import { Request } from '@cloudflare/workers-types';
import { type CloudflareVectorizeStore } from '@langchain/cloudflare';
import { OpenAIEmbeddings } from '../OpenAIEmbedder';
import { GenerativeModel } from '@google/generative-ai';
import { seededRandom } from '../util';
export async function POST(request: Request, store: CloudflareVectorizeStore, _: OpenAIEmbeddings, m: GenerativeModel, env: Env) {
const body = (await request.json()) as {
pageContent: string;
title?: string;
description?: string;
space?: string;
url: string;
user: string;
};
if (!body.pageContent || !body.url) {
return new Response(JSON.stringify({ message: 'Invalid Page Content' }), { status: 400 });
}
const { searchParams } = new URL(request.url);
const uniqueUrl = searchParams.get('uniqueUrl');
const toBeDeleted = `${uniqueUrl}-${body.user}`;
const tbduuid = await env.KV.get(toBeDeleted);
if (tbduuid) {
await store.delete({ ids: [tbduuid] });
}
// TODO: FIX THIS,BUT TEMPERORILY TRIM page content to 1000 words
body.pageContent = body.pageContent.split(' ').slice(0, 1000).join(' ');
const newPageContent = `Title: ${body.title}\nDescription: ${body.description}\nURL: ${body.url}\nContent: ${body.pageContent}`;
const ourID = `${body.url}-${body.user}`;
const random = seededRandom(ourID);
const uuid = random().toString(36).substring(2, 15) + random().toString(36).substring(2, 15);
await env.KV.put(uuid, ourID);
await store.addDocuments(
[
{
pageContent: newPageContent,
metadata: {
title: body.title?.slice(0, 50) ?? '',
description: body.description ?? '',
space: body.space ?? '',
url: body.url,
user: body.user,
},
},
],
{
ids: [uuid],
},
);
return new Response(JSON.stringify({ message: 'Document Added' }), { status: 200 });
}

View file

@ -37,7 +37,7 @@ export const queue = async (batch: MessageBatch, env: Env): Promise<void> => {
const collectedDocsUUIDs: {
document: {
pageContent: string;
metadata: { title: string; description: string; space: string; url: string; user: string };
metadata: { title: string; description: string; space?: string; url: string; user: string };
id: string;
};
}[] = [];
@ -57,7 +57,6 @@ export const queue = async (batch: MessageBatch, env: Env): Promise<void> => {
metadata: {
title: 'Twitter Bookmark',
description: '',
space: 'Bookmarked Tweets',
url: message.postUrl,
user: limits.user,
},

View file

@ -0,0 +1,19 @@
import { Request } from '@cloudflare/workers-types';
import { type CloudflareVectorizeStore } from '@langchain/cloudflare';
import { OpenAIEmbeddings } from '../OpenAIEmbedder';
import { GenerativeModel } from '@google/generative-ai';
import { seededRandom } from '../util';
// TODO: Waiting for cloudflare to implement tojson so i can get all IDS for that user and delete them
export async function DELETE(request: Request, store: CloudflareVectorizeStore, _: OpenAIEmbeddings, m: GenerativeModel, env: Env) {
const { searchParams } = new URL(request.url);
const user = searchParams.get('user');
console.log(store.toJSONNotImplemented());
// for (const match of matches.matches) {
// await store.delete({ ids: [match.id] });
// }
return new Response(JSON.stringify({ message: 'Document deleted' }), { status: 200 });
}

View file

@ -5,7 +5,7 @@ compatibility_flags = ['nodejs_compat']
[[vectorize]]
binding = "VECTORIZE_INDEX"
index_name = "supermem-vector"
index_name = "supermem-vector-1"
[ai]
binding = "AI"

View file

@ -13,15 +13,15 @@ CREATE TABLE `account` (
`session_state` text(255),
`oauth_token_secret` text,
`oauth_token` text,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `contentToSpace` (
`contentId` integer NOT NULL,
`spaceId` integer NOT NULL,
PRIMARY KEY(`contentId`, `spaceId`),
FOREIGN KEY (`contentId`) REFERENCES `storedContent`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`spaceId`) REFERENCES `space`(`id`) ON UPDATE no action ON DELETE no action
FOREIGN KEY (`contentId`) REFERENCES `storedContent`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`spaceId`) REFERENCES `space`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `session` (
@ -29,14 +29,14 @@ CREATE TABLE `session` (
`sessionToken` text(255) NOT NULL,
`userId` text(255) NOT NULL,
`expires` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `space` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`name` text DEFAULT 'none' NOT NULL,
`user` text(255),
FOREIGN KEY (`user`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
FOREIGN KEY (`user`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `storedContent` (
@ -50,7 +50,7 @@ CREATE TABLE `storedContent` (
`type` text DEFAULT 'page',
`image` text(255),
`user` text(255),
FOREIGN KEY (`user`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
FOREIGN KEY (`user`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `user` (

7
apps/web/db/wipe.sql Normal file
View file

@ -0,0 +1,7 @@
DELETE FROM `account`;
DELETE FROM `contentToSpace`;
DELETE FROM `session`;
DELETE FROM `space`;
DELETE FROM `storedContent`;
DELETE FROM `user`;
DELETE FROM `verificationToken`;

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
apps/web/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View file

@ -0,0 +1,19 @@
{
"name": "Supermemory - Your second brain",
"short_name": "Save your memories forever, build your own second brain.",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View file

@ -6,8 +6,33 @@ const roboto = Roboto({ weight: ["300", "400", "500"], subsets: ["latin"] });
const inter = Inter({ weight: ["300", "400", "500"], subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "Supermemory - Your second brain",
description: "Save your memories forever, build your own second brain.",
openGraph: {
images: [
{
url: "https://supermemory.dhr.wtf/og-image.png",
width: 1200,
height: 630,
},
],
siteName: "Supermemory",
title: "Supermemory - Your second brain",
description: "Save your memories forever, build your own second brain.",
},
twitter: {
card: "summary_large_image",
site: "https://supermemory.dhr.wtf",
creator: "@dhravyashah",
description: "Save your memories forever, build your own second brain.",
images: [
{
url: "https://supermemory.dhr.wtf/og-image.png",
width: 1200,
height: 630,
},
],
},
};
export default function RootLayout({