Merge branch 'main' of github.com:supermemoryai/supermemory

This commit is contained in:
Dhravya Shah 2025-03-17 15:18:48 -07:00
commit 8931c43295
6 changed files with 55 additions and 230 deletions

View file

@ -194,7 +194,7 @@ export function LandingPage() {
</li>
<li>
<a
href="https://discord.gg/supermemory"
href="https://discord.gg/b3BgKWpbtR"
target="_blank"
className="hover:text-white"
rel="noreferrer"

View file

@ -131,10 +131,6 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
// Pre-compute the vector similarity expression
const vectorSimilarity = sql<number>`1 - (embeddings <=> ${JSON.stringify(embedding[0])}::vector)`;
const textSearchRank = sql<number>`ts_rank_cd(
to_tsvector('english', coalesce(${chunk.textContent}, '')),
plainto_tsquery('english', ${queryText})
)`;
// Get matching chunks with document info
const matchingChunks = await db
@ -145,7 +141,6 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
orderInDocument: chunk.orderInDocument,
metadata: chunk.metadata,
similarity: vectorSimilarity,
textRank: textSearchRank,
// Document fields
docId: documents.id,
docUuid: documents.uuid,
@ -159,16 +154,10 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
.from(chunk)
.innerJoin(documents, eq(chunk.documentId, documents.id))
.where(
and(eq(documents.userId, user.id), sql`${vectorSimilarity} > 0.5`)
and(eq(documents.userId, user.id), sql`${vectorSimilarity} > 0.3`)
)
.orderBy(
desc(sql<number>`(
0.6 * ${vectorSimilarity} +
0.25 * ${textSearchRank} +
0.15 * (1.0 / (1.0 + extract(epoch from age(${documents.updatedAt})) / (90 * 24 * 60 * 60)))
)::float`)
)
.limit(15);
.orderBy(desc(vectorSimilarity))
.limit(25);
// Get unique document IDs from matching chunks
const uniqueDocIds = [
@ -201,9 +190,9 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
const docChunks = chunksByDocument.get(match.documentId) || [];
const matchIndex = docChunks.findIndex((c) => c.id === match.chunkId);
// Get surrounding chunks (1 before and 1 after)
const start = Math.max(0, matchIndex - 1);
const end = Math.min(docChunks.length, matchIndex + 2);
// Get surrounding chunks (2 before and 2 after for more context)
const start = Math.max(0, matchIndex - 2);
const end = Math.min(docChunks.length, matchIndex + 3);
const relevantChunks = docChunks.slice(start, end);
return {
@ -224,34 +213,23 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
};
});
// Remove duplicates based on document ID
const uniqueResults = contextualResults.reduce(
(acc, current) => {
const existingDoc = acc.find((doc) => doc.id === current.id);
if (!existingDoc) {
acc.push(current);
} else if (current.similarity > existingDoc.similarity) {
// Replace if current match is better
const index = acc.findIndex((doc) => doc.id === current.id);
acc[index] = current;
}
return acc;
},
[] as typeof contextualResults
);
// Sort by similarity and take top results
const topResults = contextualResults
.sort((a, b) => b.similarity - a.similarity)
.slice(0, 10);
data.appendMessageAnnotation(uniqueResults);
data.appendMessageAnnotation(topResults);
if (lastUserMessage) {
lastUserMessage.content =
typeof lastUserMessage.content === "string"
? lastUserMessage.content +
`<context>${JSON.stringify(uniqueResults)}</context>`
`<context>${JSON.stringify(topResults)}</context>`
: [
...lastUserMessage.content,
{
type: "text",
text: `<context>${JSON.stringify(uniqueResults)}</context>`,
text: `<context>${JSON.stringify(topResults)}</context>`,
},
];
coreMessages[coreMessages.length - 1] = lastUserMessage;
@ -310,7 +288,7 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
role: "assistant",
content:
completion.text +
`<context>[${JSON.stringify(uniqueResults)}]</context>`,
`<context>[${JSON.stringify(topResults)}]</context>`,
},
];
@ -602,14 +580,10 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
);
}
// Pre-compute the vector similarity expression to avoid multiple calculations
// Pre-compute the vector similarity expression
const vectorSimilarity = sql<number>`1 - (embeddings <=> ${JSON.stringify(embeddings.data[0])}::vector)`;
const textSearchRank = sql<number>`ts_rank_cd(
to_tsvector('english', coalesce(${chunk.textContent}, '')),
plainto_tsquery('english', ${query})
)`;
// First get the top matching chunks
// Get matching chunks
const results = await db
.select({
chunkId: chunk.id,
@ -618,7 +592,6 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
orderInDocument: chunk.orderInDocument,
metadata: chunk.metadata,
similarity: vectorSimilarity,
textRank: textSearchRank,
// Document fields
docUuid: documents.uuid,
docContent: documents.content,
@ -657,13 +630,7 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
: [])
)
)
.orderBy(
desc(sql<number>`(
0.6 * ${vectorSimilarity} +
0.25 * ${textSearchRank} +
0.15 * (1.0 / (1.0 + extract(epoch from age(${documents.updatedAt})) / (90 * 24 * 60 * 60)))
)::float`)
)
.orderBy(desc(vectorSimilarity))
.limit(limit);
// Group results by document and take the best matching chunk
@ -679,26 +646,28 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
}
// Convert back to array and format response
const finalResults = Array.from(documentResults.values()).map((r) => ({
id: r.documentId,
uuid: r.docUuid,
content: r.docContent,
type: r.docType,
url: r.docUrl,
title: r.docTitle,
createdAt: r.docCreatedAt,
updatedAt: r.docUpdatedAt,
userId: r.docUserId,
description: r.docDescription,
ogImage: r.docOgImage,
similarity: Number(r.similarity.toFixed(4)),
matchingChunk: {
id: r.chunkId,
content: r.textContent,
orderInDocument: r.orderInDocument,
metadata: r.metadata,
},
}));
const finalResults = Array.from(documentResults.values())
.sort((a, b) => b.similarity - a.similarity)
.map((r) => ({
id: r.documentId,
uuid: r.docUuid,
content: r.docContent,
type: r.docType,
url: r.docUrl,
title: r.docTitle,
createdAt: r.docCreatedAt,
updatedAt: r.docUpdatedAt,
userId: r.docUserId,
description: r.docDescription,
ogImage: r.docOgImage,
similarity: Number(r.similarity.toFixed(4)),
matchingChunk: {
id: r.chunkId,
content: r.textContent,
orderInDocument: r.orderInDocument,
metadata: r.metadata,
},
}));
return c.json({ results: finalResults });
} catch (error) {

View file

@ -77,7 +77,10 @@ export default function Hero() {
</Popover>
*/}
<a href="https://docs.supermemory.ai" className="text-gray-600 hover:text-gray-900 transition-colors">
<a
href="https://docs.supermemory.ai"
className="text-gray-600 hover:text-gray-900 transition-colors"
>
Docs
</a>
</nav>
@ -86,10 +89,16 @@ export default function Hero() {
{/* Right section */}
<div className="flex items-center space-x-6">
<div className="hidden sm:flex items-center space-x-6">
<a href="#" className="text-gray-600 hover:text-gray-900 transition-colors">
<a
href="https://git.new/memory"
className="text-gray-600 hover:text-gray-900 transition-colors"
>
<GithubIcon className="h-6 w-6" />
</a>
<a href="#" className="text-gray-600 hover:text-gray-900 transition-colors">
<a
href="https://discord.gg/b3BgKWpbtR"
className="text-gray-600 hover:text-gray-900 transition-colors"
>
<DiscordIcon className="h-6 w-6" />
</a>
</div>

View file

@ -1,5 +1,7 @@
import { LoaderFunctionArgs, redirect } from "@remix-run/cloudflare";
export async function loader({ context }: LoaderFunctionArgs) {
return redirect("https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnpoaffkcankadgjfc?hl=en");
return redirect(
"https://chromewebstore.google.com/detail/supermemory/afpgkkipfdpeaflnpoaffkcankadgjfc?hl=en",
);
}

View file

@ -48,84 +48,6 @@ export default function Onboarding() {
animate={{ opacity: 1 }}
className="flex flex-col min-h-screen items-center pt-40 relative overflow-hidden bg-gradient-to-b from-gray-900 to-gray-800 bg-opacity-40"
>
{/* Neural network background pattern */}
<div className="absolute inset-0 overflow-hidden">
{/* Subtle gradient orbs */}
{[...Array(4)].map((_, i) => (
<motion.div
key={`orb-${i}`}
className="absolute rounded-full blur-3xl opacity-20"
style={{
background: `radial-gradient(circle, ${
i % 2 === 0 ? "#3b82f6" : "#4f46e5"
} 0%, transparent 70%)`,
width: `${Math.random() * 300 + 200}px`,
height: `${Math.random() * 300 + 200}px`,
}}
animate={{
x: [Math.random() * window.innerWidth, Math.random() * window.innerWidth],
y: [Math.random() * window.innerHeight, Math.random() * window.innerHeight],
}}
transition={{
duration: 25,
repeat: Infinity,
repeatType: "reverse",
ease: "easeInOut",
}}
/>
))}
{/* Neurons */}
{[...Array(30)].map((_, i) => (
<motion.div
key={i}
className="absolute w-3 h-3 bg-blue-400/30 rounded-full"
initial={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
scale: Math.random() * 0.5 + 0.5,
}}
animate={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
scale: [null, 1.2, 1],
}}
transition={{
duration: 10 + Math.random() * 5,
repeat: Infinity,
ease: "linear",
delay: Math.random() * 2,
}}
/>
))}
{/* Synaptic connections */}
{[...Array(40)].map((_, i) => (
<motion.div
key={`line-${i}`}
className="absolute h-[1px] bg-gradient-to-r from-blue-400/20 to-transparent"
style={{
width: `${Math.random() * 200 + 100}px`,
transform: `rotate(${Math.random() * 360}deg)`,
}}
initial={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
opacity: 0.1,
}}
animate={{
opacity: [0.1, 0.3, 0.1],
}}
transition={{
duration: 4 + Math.random() * 2,
repeat: Infinity,
ease: "easeInOut",
delay: Math.random() * 2,
}}
/>
))}
</div>
{/* Logo */}
<motion.div
initial={{ y: 20, opacity: 0 }}

View file

@ -27,83 +27,6 @@ export default function Onboarding() {
animate={{ opacity: 1 }}
className="flex flex-col min-h-screen items-center pt-20 relative overflow-hidden bg-gradient-to-b from-gray-900 to-gray-800 bg-opacity-40"
>
{/* Neural network background pattern */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
{/* Subtle gradient orbs */}
{[...Array(4)].map((_, i) => (
<motion.div
key={`orb-${i}`}
className="absolute rounded-full blur-3xl opacity-20"
style={{
background: `radial-gradient(circle, ${
i % 2 === 0 ? "#3b82f6" : "#4f46e5"
} 0%, transparent 70%)`,
width: `${Math.random() * 300 + 200}px`,
height: `${Math.random() * 300 + 200}px`,
}}
animate={{
x: [Math.random() * window.innerWidth, Math.random() * window.innerWidth],
y: [Math.random() * window.innerHeight, Math.random() * window.innerHeight],
}}
transition={{
duration: 25,
repeat: Infinity,
repeatType: "reverse",
ease: "easeInOut",
}}
/>
))}
{/* Neurons */}
{[...Array(30)].map((_, i) => (
<motion.div
key={i}
className="absolute w-3 h-3 bg-blue-400/30 rounded-full"
initial={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
scale: Math.random() * 0.5 + 0.5,
}}
animate={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
scale: [null, 1.2, 1],
}}
transition={{
duration: 10 + Math.random() * 5,
repeat: Infinity,
ease: "linear",
delay: Math.random() * 2,
}}
/>
))}
{/* Synaptic connections */}
{[...Array(40)].map((_, i) => (
<motion.div
key={`line-${i}`}
className="absolute h-[1px] bg-gradient-to-r from-blue-400/20 to-transparent"
style={{
width: `${Math.random() * 200 + 100}px`,
transform: `rotate(${Math.random() * 360}deg)`,
}}
initial={{
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight,
opacity: 0.1,
}}
animate={{
opacity: [0.1, 0.3, 0.1],
}}
transition={{
duration: 4 + Math.random() * 2,
repeat: Infinity,
ease: "easeInOut",
delay: Math.random() * 2,
}}
/>
))}
</div>
{/* Logo */}
<motion.div