Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions apps/docs/ai-sdk/user-profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ The `MemoryPromptData` object passed to your template function provides:

- `userMemories`: Pre-formatted markdown combining static profile facts (name, preferences, goals) and dynamic context (current projects, recent interests)
- `generalSearchMemories`: Pre-formatted search results based on semantic similarity to the current query (empty string if mode is "profile")
- `searchResults`: Raw search results array (`Array<{ memory: string; metadata?: Record<string, unknown> }>`) for traversing, filtering, or selectively including results based on metadata

### XML-Based Prompting for Claude

Expand All @@ -179,6 +180,31 @@ const model = withSupermemory(anthropic("claude-3-sonnet"), "user-123", {
})
```

### Filtering Search Results

Use `searchResults` to traverse the raw data and pick what's important:

```typescript
const selectivePrompt = (data: MemoryPromptData) => {
const relevant = data.searchResults.filter(
(r) => (r.metadata?.score as number) > 0.7
)
return `
<user_memories>
${data.userMemories}
</user_memories>
<relevant_context>
${relevant.map((r) => `- ${r.memory}`).join("\n")}
</relevant_context>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The documentation example for filtering search results uses r.metadata?.score, but the API returns the score in the top-level similarity field, causing the filter to fail.
Severity: MEDIUM

Suggested Fix

Update the documentation example in apps/docs/ai-sdk/user-profiles.mdx to filter by r.similarity instead of r.metadata?.score. The corrected code should be const relevant = data.searchResults.filter((r) => r.similarity > 0.7).

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: apps/docs/ai-sdk/user-profiles.mdx#L198

Potential issue: The documentation example for filtering memory search results
incorrectly references `r.metadata?.score`. The actual API response places the
similarity score in a top-level `similarity` field. As a result, any user code following
this example will have the filter condition `(r.metadata?.score as number) > 0.7`
evaluate to `false`, because `r.metadata?.score` is `undefined`. This will cause all
search results to be filtered out, leading to an empty `relevant` array and preventing
the intended user profile information from being included in the prompt.

Did we get this right? 👍 / 👎 to inform future reviews.

`.trim()
}

const model = withSupermemory(openai("gpt-4"), "user-123", {
mode: "full",
promptTemplate: selectivePrompt
})
```

### Custom Branding

Remove "supermemories" references and use your own branding:
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/integrations/ai-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const model = withSupermemory(openai("gpt-4"), "user-123", { mode: "full" })

### Custom Prompt Templates

Customize how memories are formatted:
Customize how memories are formatted. The template receives `userMemories`, `generalSearchMemories`, and `searchResults` (raw array for filtering by metadata):

```typescript
import { withSupermemory, type MemoryPromptData } from "@supermemory/tools/ai-sdk"
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/integrations/mastra.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ await agent.generate("My favorite framework is Next.js")

## Custom Prompt Templates

Customize how memories are formatted and injected:
Customize how memories are formatted and injected. The template receives `userMemories`, `generalSearchMemories`, and `searchResults` (raw array for filtering by metadata):

```typescript
import { Agent } from "@mastra/core/agent"
Expand Down
1 change: 1 addition & 0 deletions packages/tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ const result = await generateText({
The `MemoryPromptData` object provides:
- `userMemories`: Pre-formatted markdown combining static profile facts (name, preferences, goals) and dynamic context (current projects, recent interests)
- `generalSearchMemories`: Pre-formatted search results based on semantic similarity to the current query
- `searchResults`: Raw search results array for traversing, filtering, or selectively including results based on metadata

### OpenAI SDK Usage

Expand Down
2 changes: 1 addition & 1 deletion packages/tools/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@supermemory/tools",
"type": "module",
"version": "1.4.00",
"version": "1.4.01",
"description": "Memory tools for AI SDK and OpenAI function calling with supermemory",
"scripts": {
"build": "tsdown",
Expand Down
1 change: 1 addition & 0 deletions packages/tools/src/shared/memory-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export const buildMemoriesText = async (
const promptData: MemoryPromptData = {
userMemories,
generalSearchMemories,
searchResults: memoriesResponse.searchResults?.results ?? [],
}

const memories = promptTemplate(promptData)
Expand Down
7 changes: 7 additions & 0 deletions packages/tools/src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export interface MemoryPromptData {
* Empty string if mode is "profile" only.
*/
generalSearchMemories: string
/**
* Raw search results from the API for the current query.
* Use this to traverse, filter, or selectively include results based on metadata.
* Empty array if mode is "profile" or when no search was performed.
*/
searchResults: Array<{ memory: string; metadata?: Record<string, unknown> }>
}

/**
Expand All @@ -28,6 +34,7 @@ export interface MemoryPromptData {
* ${data.generalSearchMemories}
* </user_memories>
* `.trim()
* // data.searchResults provides raw results for custom filtering/formatting
* ```
*/
export type PromptTemplate = (data: MemoryPromptData) => string
Expand Down
7 changes: 2 additions & 5 deletions packages/tools/src/vercel/memory-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export {
type BuildMemoriesTextOptions,
} from "../shared"

import type { Logger } from "../shared"
import type { Logger, MemoryPromptData } from "../shared"
import type { LanguageModelCallOptions } from "./util"

/**
Expand Down Expand Up @@ -100,10 +100,7 @@ export const addSystemPrompt = async (
mode: "profile" | "query" | "full",
baseUrl: string,
apiKey: string,
promptTemplate?: (data: {
userMemories: string
generalSearchMemories: string
}) => string,
promptTemplate?: (data: MemoryPromptData) => string,
): Promise<LanguageModelCallOptions> => {
const { buildMemoriesText } = await import("../shared")

Expand Down
Loading