feat(skills): introduce Mem0 skill graph with dedicated CLI and Vercel AI SDK skills (#4725)
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
# Memory Utilities Reference
|
||||
|
||||
Complete reference for standalone utility functions exported from `@mem0/vercel-ai-provider`. These functions give you manual control over memory retrieval and storage, independent of the wrapped model pattern.
|
||||
|
||||
Source: `vercel-ai-sdk/src/mem0-utils.ts`
|
||||
|
||||
## `addMemories(messages, config?)`
|
||||
|
||||
Stores messages to Mem0 as new memories.
|
||||
|
||||
```typescript
|
||||
import { addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
await addMemories(
|
||||
[
|
||||
{ role: "user", content: [{ type: "text", text: "I love Italian food" }] },
|
||||
{ role: "assistant", content: [{ type: "text", text: "Noted! I'll remember that." }] },
|
||||
],
|
||||
{ user_id: "alice", mem0ApiKey: "m0-xxx" }
|
||||
);
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
async function addMemories(
|
||||
messages: LanguageModelV2Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `messages` | `LanguageModelV2Prompt \| string` | Messages to store. If a string, wrapped as `[{ role: "user", content: string }]` |
|
||||
| `config` | `Mem0ConfigSettings` | Optional. Must include entity scope (`user_id`, etc.) and API key |
|
||||
|
||||
**Behavior:**
|
||||
1. If `messages` is a string, wraps it as a single user message
|
||||
2. Otherwise, converts `LanguageModelV2Prompt` to Mem0 format via `convertToMem0Format` (handles multimodal content)
|
||||
3. Calls `POST /v1/memories/` with the converted messages and config
|
||||
|
||||
**Returns:** The API response from Mem0 (memory operation result).
|
||||
|
||||
---
|
||||
|
||||
## `retrieveMemories(prompt, config?)`
|
||||
|
||||
Retrieves memories and returns a **formatted system prompt string** ready to inject into a `system` parameter.
|
||||
|
||||
```typescript
|
||||
import { retrieveMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const systemPrompt = await retrieveMemories("What restaurants do I like?", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
});
|
||||
// Returns: "System Message: These are the memories I have stored... Memory: User loves Italian food\n\n ..."
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
async function retrieveMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<string>;
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `config` | `Mem0ConfigSettings` | Optional. Entity scope and API key |
|
||||
|
||||
**Behavior:**
|
||||
1. Flattens the prompt to a plain string (extracts text from `LanguageModelV2Prompt` parts)
|
||||
2. Calls `searchInternalMemories` (`POST /v2/memories/search/`)
|
||||
3. Formats each memory as `"Memory: {memory.memory}\n\n"`
|
||||
4. If `enable_graph: true`, also appends graph relations as `"Relation: {source} -> {relationship} -> {target}\n\n"`
|
||||
5. Wraps everything in a system prompt preamble
|
||||
|
||||
**Returns:** A **string** containing the formatted system prompt with embedded memories. Returns `""` (empty string) if no memories found.
|
||||
|
||||
**Output format:**
|
||||
```
|
||||
System Message: These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message:
|
||||
|
||||
Memory: User loves Italian food
|
||||
|
||||
Memory: User is vegetarian
|
||||
|
||||
HERE ARE THE GRAPHS RELATIONS FOR THE PREFERENCES OF THE USER:
|
||||
|
||||
Relation: Alice -> likes -> Italian cuisine
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `getMemories(prompt, config?)`
|
||||
|
||||
Retrieves memories and returns the **raw memory array** (or full response if graph is enabled).
|
||||
|
||||
```typescript
|
||||
import { getMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const memories = await getMemories("What are my preferences?", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
});
|
||||
// Returns: [{ memory: "User loves Italian food", id: "...", ... }, ...]
|
||||
|
||||
// With graph enabled:
|
||||
const graphMemories = await getMemories("What are my preferences?", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
enable_graph: true,
|
||||
});
|
||||
// Returns: { results: [...], relations: [...] }
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
async function getMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `config` | `Mem0ConfigSettings` | Optional. Entity scope and API key |
|
||||
|
||||
**Behavior:**
|
||||
1. Flattens the prompt to a plain string
|
||||
2. Calls `searchInternalMemories` (`POST /v2/memories/search/`)
|
||||
3. If `enable_graph` is **not** set: returns `memories.results` (the array of memory objects)
|
||||
4. If `enable_graph` is set: returns the full response object (with both `results` and `relations`)
|
||||
|
||||
**Returns:** Memory object array, or full response object when graph is enabled.
|
||||
|
||||
---
|
||||
|
||||
## `searchMemories(prompt, config?)`
|
||||
|
||||
Retrieves the **full search API response** including results, relations, scores, and metadata.
|
||||
|
||||
```typescript
|
||||
import { searchMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const response = await searchMemories("cooking preferences", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
});
|
||||
// Returns: { results: [{ memory: "...", score: 0.95, ... }], relations: [...] }
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
async function searchMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `config` | `Mem0ConfigSettings` | Optional. Entity scope and API key |
|
||||
|
||||
**Behavior:**
|
||||
1. Flattens the prompt to a plain string
|
||||
2. Calls `searchInternalMemories` (`POST /v2/memories/search/`)
|
||||
3. Returns the full response without any filtering
|
||||
|
||||
**Returns:** The complete API response object. On error, returns `[]`.
|
||||
|
||||
**Note:** Unlike `getMemories`, this always returns the full response regardless of `enable_graph` setting.
|
||||
|
||||
---
|
||||
|
||||
## When to Use Which Function
|
||||
|
||||
| Function | Returns | Use when |
|
||||
|----------|---------|----------|
|
||||
| `retrieveMemories` | Formatted system prompt **string** | Injecting directly into a `system` parameter for `generateText`/`streamText` |
|
||||
| `getMemories` | Memory **array** (or full response if `enable_graph`) | Processing memories programmatically (filtering, transforming, counting) |
|
||||
| `searchMemories` | Full API **response** (results + relations) | Need relations, similarity scores, or complete metadata regardless of graph setting |
|
||||
| `addMemories` | API response | Storing new conversation messages as memories |
|
||||
|
||||
## Internal: `searchInternalMemories(query, config?, top_k?)`
|
||||
|
||||
Not exported. Used by all retrieval functions.
|
||||
|
||||
```typescript
|
||||
async function searchInternalMemories(
|
||||
query: string,
|
||||
config?: Mem0ConfigSettings,
|
||||
top_k: number = 5
|
||||
): Promise<any>;
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
1. Builds an `OR` filter from entity identifiers (`user_id`, `app_id`, `agent_id`, `run_id`)
|
||||
2. Resolves org/project identifiers (`org_id` takes precedence over `org_name`)
|
||||
3. Loads the API key from `config.mem0ApiKey` or `MEM0_API_KEY` env var
|
||||
4. Calls `POST {host}/v2/memories/search/` with:
|
||||
- `query`: the search string
|
||||
- `filters`: the OR filter object
|
||||
- `top_k`: from config or default 5
|
||||
- `version`: `"v2"`
|
||||
- `output_format`: `"v1.1"`
|
||||
- All other config fields spread into the request body
|
||||
|
||||
**Default host:** `https://api.mem0.ai`
|
||||
|
||||
## Internal: `convertToMem0Format(messages)`
|
||||
|
||||
Not exported. Used by `addMemories` to convert `LanguageModelV2Prompt` messages to Mem0's format.
|
||||
|
||||
**Multimodal content mapping:**
|
||||
|
||||
| Input type | Input format | Output type | Output format |
|
||||
|-----------|-------------|-------------|---------------|
|
||||
| Text | `{ type: "text", text: "..." }` | Plain string | `{ role, content: "..." }` |
|
||||
| Image | `{ type: "image_url", image_url: { url } }` or `{ type: "image", ... }` | Image URL | `{ role, content: { type: "image_url", image_url: { url } } }` |
|
||||
| PDF file | `{ type: "file", data: url, mediaType: "application/pdf" }` | PDF URL | `{ role, content: { type: "pdf_url", pdf_url: { url } } }` |
|
||||
| Markdown file | `{ type: "file", data: url, mediaType: "text/markdown" }` or `"application/mdx"` | MDX URL | `{ role, content: { type: "mdx_url", mdx_url: { url } } }` |
|
||||
| Image file | `{ type: "file", data: url, mediaType: "image/*" }` | Image URL | `{ role, content: { type: "image_url", image_url: { url } } }` |
|
||||
| MDX content | `{ type: "mdx_url", mdx_url: { url } }` or `{ type: "mdx", ... }` | MDX URL | `{ role, content: { type: "mdx_url", mdx_url: { url } } }` |
|
||||
| PDF content | `{ type: "pdf_url", pdf_url: { url } }` or `{ type: "pdf", ... }` | PDF URL | `{ role, content: { type: "pdf_url", pdf_url: { url } } }` |
|
||||
|
||||
The function handles three message content shapes:
|
||||
1. **String content**: passed through directly
|
||||
2. **Array content**: each element mapped individually, nulls filtered out
|
||||
3. **Single object content**: mapped as a single element
|
||||
|
||||
## Internal: `flattenPrompt(prompt)`
|
||||
|
||||
Not exported. Extracts plain text from `LanguageModelV2Prompt` for use as a search query.
|
||||
|
||||
- Iterates over prompt parts, extracting text from `user` role messages
|
||||
- For `text` type content: extracts `.text`
|
||||
- For `file` type content: returns descriptive placeholders (`[PDF document]`, `[Markdown document]`, `[Image]`, `[File attachment]`)
|
||||
- For other content types: returns `[multimodal content]`
|
||||
- Joins all parts with spaces
|
||||
|
||||
## `Mem0ConfigSettings` Fields Reference
|
||||
|
||||
All fields are optional. Used across all utility functions.
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `user_id` | `string` | -- | Scope memories to a user |
|
||||
| `app_id` | `string` | -- | Scope memories to an application |
|
||||
| `agent_id` | `string` | -- | Scope memories to an agent |
|
||||
| `run_id` | `string` | -- | Scope memories to a session/run |
|
||||
| `org_name` | `string` | -- | Organization name (fallback if `org_id` not set) |
|
||||
| `project_name` | `string` | -- | Project name (fallback if `org_id` not set) |
|
||||
| `org_id` | `string` | -- | Organization ID (takes precedence) |
|
||||
| `project_id` | `string` | -- | Project ID |
|
||||
| `metadata` | `Record<string, any>` | -- | Custom metadata |
|
||||
| `filters` | `Record<string, any>` | -- | Custom search filters |
|
||||
| `infer` | `boolean` | -- | Enable inference |
|
||||
| `page` | `number` | -- | Pagination page number |
|
||||
| `page_size` | `number` | -- | Results per page |
|
||||
| `mem0ApiKey` | `string` | `MEM0_API_KEY` env | Mem0 API key |
|
||||
| `top_k` | `number` | `5` | Number of memories to retrieve |
|
||||
| `threshold` | `number` | -- | Minimum similarity score |
|
||||
| `rerank` | `boolean` | -- | Enable re-ranking |
|
||||
| `enable_graph` | `boolean` | -- | Enable graph memory (relations) |
|
||||
| `host` | `string` | `https://api.mem0.ai` | Custom API host |
|
||||
| `output_format` | `string` | -- | Output format version |
|
||||
| `filter_memories` | `boolean` | -- | Enable memory filtering |
|
||||
| `async_mode` | `boolean` | -- | Enable async processing |
|
||||
@@ -0,0 +1,239 @@
|
||||
# Provider API Reference
|
||||
|
||||
Complete reference for the `@mem0/vercel-ai-provider` provider layer. Source: `vercel-ai-sdk/src/`.
|
||||
|
||||
## `createMem0(options?)`
|
||||
|
||||
Factory function that creates a `Mem0Provider` instance. This is the primary entry point for the wrapped model approach.
|
||||
|
||||
```typescript
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0(); // defaults: provider "openai"
|
||||
const mem0 = createMem0({ provider: "anthropic" }); // use Anthropic as LLM backend
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
function createMem0(options?: Mem0ProviderSettings): Mem0Provider;
|
||||
```
|
||||
|
||||
When called with no arguments, defaults to `{ provider: "openai" }`.
|
||||
|
||||
**Returns:** `Mem0Provider` -- a callable function that also exposes `.chat()`, `.completion()`, and `.languageModel()` methods.
|
||||
|
||||
## `Mem0Provider` Interface
|
||||
|
||||
Implements `ProviderV2` from `@ai-sdk/provider`.
|
||||
|
||||
```typescript
|
||||
interface Mem0Provider extends ProviderV2 {
|
||||
// Call directly as a function
|
||||
(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
|
||||
// Or use named methods
|
||||
chat(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
completion(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
languageModel(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
}
|
||||
```
|
||||
|
||||
- **Direct call** (`mem0("gpt-4-turbo", {...})`): creates a generic language model (neither chat nor completion mode forced).
|
||||
- **`chat()`**: creates a model with `modelType: "chat"` (note: in the current source, the chat constructor sets `modelType: "completion"` -- this appears to be a bug; functionally equivalent to `completion()` at present).
|
||||
- **`completion()`**: creates a model with `modelType: "completion"`.
|
||||
- **`languageModel()`**: alias for the generic model (same as direct call).
|
||||
|
||||
All three return a `Mem0GenericLanguageModel` instance implementing `LanguageModelV2`.
|
||||
|
||||
## `Mem0ProviderSettings` Interface
|
||||
|
||||
Configuration passed to `createMem0()`.
|
||||
|
||||
```typescript
|
||||
interface Mem0ProviderSettings {
|
||||
baseURL?: string; // Base URL for the LLM provider (default: "http://api.openai.com")
|
||||
headers?: Record<string, string>; // Custom headers for LLM requests
|
||||
provider?: string; // LLM provider name (default: "openai")
|
||||
mem0ApiKey?: string; // Mem0 Platform API key (or use MEM0_API_KEY env var)
|
||||
apiKey?: string; // LLM provider API key (e.g., OpenAI key)
|
||||
mem0Config?: Mem0Config; // Default Mem0 config (user_id, etc.) applied to all calls
|
||||
config?: LLMProviderSettings; // Provider-specific settings (OpenAI, Anthropic, etc.)
|
||||
fetch?: typeof fetch; // Custom fetch implementation (for testing/middleware)
|
||||
generateId?: () => string; // Custom ID generator (internal use)
|
||||
name?: string; // Provider instance name
|
||||
modelType?: "completion" | "chat"; // Force model type
|
||||
}
|
||||
```
|
||||
|
||||
### Key fields explained
|
||||
|
||||
| Field | Purpose | Example |
|
||||
|-------|---------|---------|
|
||||
| `provider` | Which LLM backend to use | `"openai"`, `"anthropic"`, `"google"`, `"groq"`, `"cohere"` |
|
||||
| `mem0ApiKey` | Mem0 Platform API key | `"m0-xxx"` |
|
||||
| `apiKey` | LLM provider API key | `"sk-xxx"` (OpenAI), `"sk-ant-xxx"` (Anthropic) |
|
||||
| `mem0Config` | Default Mem0 settings for all calls | `{ user_id: "alice", enable_graph: true }` |
|
||||
| `config` | Provider-specific SDK settings | `{ organization: "org-xxx" }` for OpenAI |
|
||||
| `baseURL` | Override LLM provider base URL | `"https://my-proxy.example.com"` |
|
||||
|
||||
## `mem0` Singleton
|
||||
|
||||
A pre-configured instance using default settings (OpenAI provider, no API keys set -- relies on env vars).
|
||||
|
||||
```typescript
|
||||
import { mem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
|
||||
Equivalent to `createMem0()` with no arguments.
|
||||
|
||||
## `Mem0ConfigSettings` Interface
|
||||
|
||||
Configuration for memory operations. Used as `Mem0ChatSettings` (per-call) or `Mem0Config` (provider-level default). All fields are optional.
|
||||
|
||||
```typescript
|
||||
interface Mem0ConfigSettings {
|
||||
user_id?: string; // Scope memories to a specific user
|
||||
app_id?: string; // Scope memories to an application
|
||||
agent_id?: string; // Scope memories to an agent
|
||||
run_id?: string; // Scope memories to a specific run/session
|
||||
org_name?: string; // Organization name (used if org_id not set)
|
||||
project_name?: string; // Project name (used if org_id not set)
|
||||
org_id?: string; // Organization ID (takes precedence over org_name)
|
||||
project_id?: string; // Project ID (takes precedence over project_name)
|
||||
metadata?: Record<string, any>; // Custom metadata attached to memories
|
||||
filters?: Record<string, any>; // Custom filters for memory search
|
||||
infer?: boolean; // Enable inference during memory operations
|
||||
page?: number; // Pagination: page number
|
||||
page_size?: number; // Pagination: results per page
|
||||
mem0ApiKey?: string; // Mem0 API key (overrides provider-level key)
|
||||
top_k?: number; // Number of memories to retrieve (default: 5)
|
||||
threshold?: number; // Minimum similarity score for retrieval
|
||||
rerank?: boolean; // Enable re-ranking of search results
|
||||
enable_graph?: boolean; // Enable graph memory (returns relations)
|
||||
host?: string; // Custom Mem0 API host (default: "https://api.mem0.ai")
|
||||
output_format?: string; // Output format version
|
||||
filter_memories?: boolean; // Enable memory filtering
|
||||
async_mode?: boolean; // Enable async processing of memory operations
|
||||
}
|
||||
```
|
||||
|
||||
## `Mem0ChatConfig` Type
|
||||
|
||||
Combined type used internally by the language model. Merges memory config with provider config.
|
||||
|
||||
```typescript
|
||||
interface Mem0ChatConfig extends Mem0ConfigSettings, Mem0ProviderSettings {}
|
||||
```
|
||||
|
||||
This means a `Mem0ChatConfig` has all fields from both `Mem0ConfigSettings` and `Mem0ProviderSettings`.
|
||||
|
||||
## `Mem0ChatSettings` Type
|
||||
|
||||
Alias for `Mem0ConfigSettings`. Passed as the second argument when creating a model:
|
||||
|
||||
```typescript
|
||||
mem0("gpt-4-turbo", { user_id: "alice", enable_graph: true })
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// This object is Mem0ChatSettings
|
||||
```
|
||||
|
||||
## `LLMProviderSettings` Type
|
||||
|
||||
Union of provider-specific settings. Extends all supported provider setting interfaces:
|
||||
|
||||
```typescript
|
||||
interface LLMProviderSettings extends
|
||||
OpenAIProviderSettings,
|
||||
AnthropicProviderSettings,
|
||||
CohereProviderSettings,
|
||||
GroqProviderSettings {}
|
||||
```
|
||||
|
||||
Pass via the `config` field of `Mem0ProviderSettings` to forward settings to the underlying LLM provider SDK.
|
||||
|
||||
## Provider Selection: `Mem0ClassSelector`
|
||||
|
||||
Internal class that maps the `provider` string to the correct AI SDK provider.
|
||||
|
||||
```typescript
|
||||
class Mem0ClassSelector {
|
||||
static supportedProviders = ["openai", "anthropic", "cohere", "groq", "google"];
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**Important:** The `"gemini"` alias exists in the provider switch statement (maps to `createGoogleGenerativeAI`) but is **NOT** in the `supportedProviders` list. The constructor validates against `supportedProviders`, so using `"gemini"` will throw `"Model not supported: gemini"`. Use `"google"` instead.
|
||||
|
||||
### Provider mapping
|
||||
|
||||
| Config value | SDK used | Factory function |
|
||||
|-------------|----------|------------------|
|
||||
| `"openai"` | `@ai-sdk/openai` | `createOpenAI` |
|
||||
| `"anthropic"` | `@ai-sdk/anthropic` | `createAnthropic` |
|
||||
| `"cohere"` | `@ai-sdk/cohere` | `createCohere` |
|
||||
| `"groq"` | `@ai-sdk/groq` | `createGroq` |
|
||||
| `"google"` | `@ai-sdk/google` | `createGoogleGenerativeAI` |
|
||||
|
||||
## `Mem0` Facade Class
|
||||
|
||||
An alternative exported class that creates models directly without the callable-function pattern.
|
||||
|
||||
```typescript
|
||||
import { Mem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = new Mem0({ provider: "openai" });
|
||||
const chatModel = mem0.chat("gpt-4-turbo", { user_id: "alice" });
|
||||
const completionModel = mem0.completion("gpt-3.5-turbo-instruct");
|
||||
```
|
||||
|
||||
The facade defaults its base URL to `"http://127.0.0.1:11434/api"` (Ollama-style) rather than `"http://api.openai.com"`. It always uses `"openai"` as the provider for created models.
|
||||
|
||||
**Methods:**
|
||||
- `chat(modelId, settings?)` -- creates a model with `modelType: "chat"`
|
||||
- `completion(modelId, settings?)` -- creates a model with `modelType: "completion"`
|
||||
|
||||
## `Mem0GenericLanguageModel` Class
|
||||
|
||||
The core class implementing `LanguageModelV2`. Created by `createMem0` or the `Mem0` facade.
|
||||
|
||||
```typescript
|
||||
class Mem0GenericLanguageModel implements LanguageModelV2 {
|
||||
readonly specificationVersion = "v2";
|
||||
readonly defaultObjectGenerationMode = "json";
|
||||
readonly supportsImageUrls = false;
|
||||
readonly supportedUrls: Record<string, RegExp[]> = { '*': [/.*/] };
|
||||
|
||||
provider: string; // e.g., "openai"
|
||||
modelId: string; // e.g., "gpt-4-turbo"
|
||||
settings: Mem0ChatSettings;
|
||||
config: Mem0ChatConfig;
|
||||
|
||||
async doGenerate(options: LanguageModelV2CallOptions): Promise<...>;
|
||||
async doStream(options: LanguageModelV2CallOptions): Promise<...>;
|
||||
}
|
||||
```
|
||||
|
||||
Both `doGenerate` and `doStream` follow the same internal flow:
|
||||
|
||||
1. Build `Mem0ConfigSettings` from `config.mem0Config` merged with `settings`
|
||||
2. Call `processMemories`:
|
||||
- Fire `addMemories` as fire-and-forget (no await, `.then().catch()`)
|
||||
- Await `getMemories` to retrieve relevant memories
|
||||
- Format memories as a system message and prepend to the prompt
|
||||
3. Create the underlying LLM model via `Mem0ClassSelector`
|
||||
4. Delegate to the underlying model's `doGenerate` or `doStream`
|
||||
5. Return the result
|
||||
|
||||
## Type: `Mem0ChatModelId`
|
||||
|
||||
```typescript
|
||||
type Mem0ChatModelId = string & NonNullable<unknown>;
|
||||
```
|
||||
|
||||
Any non-null string. The model ID is passed through to the underlying provider (e.g., `"gpt-4-turbo"`, `"claude-sonnet-4-20250514"`, `"gemini-pro"`).
|
||||
@@ -0,0 +1,431 @@
|
||||
# Usage Patterns and Examples
|
||||
|
||||
Working examples for `@mem0/vercel-ai-provider`. All examples assume environment variables `MEM0_API_KEY` and the relevant LLM provider API key are set.
|
||||
|
||||
## 1. Wrapped Model with generateText (Basic)
|
||||
|
||||
The simplest way to add memory to any LLM call.
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
prompt: "Recommend a restaurant based on my preferences",
|
||||
});
|
||||
|
||||
console.log(text);
|
||||
```
|
||||
|
||||
Memories are automatically retrieved before the call and stored after.
|
||||
|
||||
## 2. Wrapped Model with streamText (Streaming)
|
||||
|
||||
Stream responses with automatic memory augmentation.
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
const result = streamText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
prompt: "What should I cook for dinner tonight?",
|
||||
});
|
||||
|
||||
for await (const chunk of result.textStream) {
|
||||
process.stdout.write(chunk);
|
||||
}
|
||||
```
|
||||
|
||||
Memory retrieval happens before streaming begins. The conversation is stored to Mem0 as a fire-and-forget call (non-blocking).
|
||||
|
||||
## 3. Standalone Utilities with OpenAI
|
||||
|
||||
Full control over the memory lifecycle using standalone functions with OpenAI.
|
||||
|
||||
```typescript
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import { generateText } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const userId = "alice";
|
||||
const prompt = "Suggest a weekend trip";
|
||||
|
||||
// Step 1: Retrieve memories as a formatted system prompt
|
||||
const memories = await retrieveMemories(prompt, {
|
||||
user_id: userId,
|
||||
});
|
||||
|
||||
// Step 2: Generate with the memories injected as system context
|
||||
const { text } = await generateText({
|
||||
model: openai("gpt-4-turbo"),
|
||||
prompt,
|
||||
system: memories,
|
||||
});
|
||||
|
||||
console.log(text);
|
||||
|
||||
// Step 3: Store the conversation as new memories
|
||||
await addMemories(
|
||||
[
|
||||
{ role: "user", content: [{ type: "text", text: prompt }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
{ user_id: userId }
|
||||
);
|
||||
```
|
||||
|
||||
## 4. Standalone Utilities with Anthropic
|
||||
|
||||
Same pattern, different LLM provider.
|
||||
|
||||
```typescript
|
||||
import { anthropic } from "@ai-sdk/anthropic";
|
||||
import { generateText } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const prompt = "Help me plan my exercise routine";
|
||||
const config = { user_id: "bob" };
|
||||
|
||||
const memories = await retrieveMemories(prompt, config);
|
||||
|
||||
const { text } = await generateText({
|
||||
model: anthropic("claude-sonnet-4-20250514"),
|
||||
prompt,
|
||||
system: memories,
|
||||
});
|
||||
|
||||
await addMemories(
|
||||
[
|
||||
{ role: "user", content: [{ type: "text", text: prompt }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
config
|
||||
);
|
||||
```
|
||||
|
||||
## 5. Structured Output with generateObject
|
||||
|
||||
Use with `generateObject` for typed, structured responses enriched with memory.
|
||||
|
||||
```typescript
|
||||
import { generateObject } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
import { z } from "zod";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { object } = await generateObject({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
prompt: "Suggest a meal plan for today",
|
||||
schema: z.object({
|
||||
breakfast: z.string(),
|
||||
lunch: z.string(),
|
||||
dinner: z.string(),
|
||||
snacks: z.array(z.string()),
|
||||
notes: z.string().describe("Personalization notes based on known preferences"),
|
||||
}),
|
||||
});
|
||||
|
||||
console.log(object);
|
||||
// { breakfast: "Avocado toast (you mentioned loving it)", lunch: "...", ... }
|
||||
```
|
||||
|
||||
The `defaultObjectGenerationMode` is `"json"`, so structured output works out of the box.
|
||||
|
||||
## 6. Graph Memory Enabled
|
||||
|
||||
Retrieve both text memories and entity relationship graphs.
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
}),
|
||||
prompt: "What connections do you know about between my friends?",
|
||||
});
|
||||
|
||||
console.log(text);
|
||||
```
|
||||
|
||||
With `enable_graph: true`, the system prompt includes both:
|
||||
- **Text memories**: `"Memory: Alice is friends with Bob"`
|
||||
- **Graph relations**: `"Relation: Alice -> friends_with -> Bob"`
|
||||
|
||||
### Using graph with standalone utilities
|
||||
|
||||
```typescript
|
||||
import { getMemories, searchMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
// getMemories with graph returns the full response
|
||||
const graphResult = await getMemories("my social connections", {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
});
|
||||
console.log(graphResult.results); // memory objects
|
||||
console.log(graphResult.relations); // graph relations
|
||||
|
||||
// searchMemories always returns the full response
|
||||
const fullResponse = await searchMemories("my social connections", {
|
||||
user_id: "alice",
|
||||
});
|
||||
console.log(fullResponse.results);
|
||||
console.log(fullResponse.relations);
|
||||
```
|
||||
|
||||
## 7. Multi-Provider Setup
|
||||
|
||||
Configure different LLM providers with the wrapped model.
|
||||
|
||||
### OpenAI (default)
|
||||
|
||||
```typescript
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0(); // defaults to "openai"
|
||||
const model = mem0("gpt-4-turbo", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### Anthropic
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({ provider: "anthropic" });
|
||||
const model = mem0("claude-sonnet-4-20250514", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### Google
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({ provider: "google" });
|
||||
const model = mem0("gemini-2.0-flash", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### Groq
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({ provider: "groq" });
|
||||
const model = mem0("llama-3.3-70b-versatile", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### Cohere
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({ provider: "cohere" });
|
||||
const model = mem0("command-r-plus", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### With explicit API keys (no env vars)
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({
|
||||
provider: "openai",
|
||||
apiKey: "sk-xxx", // OpenAI API key
|
||||
mem0ApiKey: "m0-xxx", // Mem0 API key
|
||||
});
|
||||
```
|
||||
|
||||
## 8. Next.js API Route Integration
|
||||
|
||||
A POST handler that uses the wrapped model in a Next.js App Router API route.
|
||||
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
import { streamText } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, userId } = await req.json();
|
||||
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
const result = streamText({
|
||||
model: mem0("gpt-4-turbo", { user_id: userId }),
|
||||
prompt: lastMessage.content,
|
||||
});
|
||||
|
||||
return result.toDataStreamResponse();
|
||||
}
|
||||
```
|
||||
|
||||
### With standalone utilities for more control
|
||||
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import { streamText } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, userId } = await req.json();
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
// Retrieve relevant memories
|
||||
const memories = await retrieveMemories(lastMessage.content, {
|
||||
user_id: userId,
|
||||
});
|
||||
|
||||
// Stream the response
|
||||
const result = streamText({
|
||||
model: openai("gpt-4-turbo"),
|
||||
prompt: lastMessage.content,
|
||||
system: memories,
|
||||
});
|
||||
|
||||
// Store conversation in the background (fire-and-forget)
|
||||
result.text.then(async (text) => {
|
||||
await addMemories(
|
||||
[
|
||||
{ role: "user", content: [{ type: "text", text: lastMessage.content }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
{ user_id: userId }
|
||||
);
|
||||
});
|
||||
|
||||
return result.toDataStreamResponse();
|
||||
}
|
||||
```
|
||||
|
||||
## 9. How Memory Processing Works Internally
|
||||
|
||||
### Wrapped model flow (doGenerate / doStream)
|
||||
|
||||
```
|
||||
1. doGenerate(options) or doStream(options) is called
|
||||
2. processMemories(messagesPrompts, mem0Config):
|
||||
a. addMemories(messagesPrompts, mem0Config)
|
||||
--> fire-and-forget: .then().catch(), NO await
|
||||
--> POST /v1/memories/ with converted messages
|
||||
b. await getMemories(messagesPrompts, mem0Config)
|
||||
--> POST /v2/memories/search/ with flattened prompt
|
||||
--> returns memory array (or {results, relations} if enable_graph)
|
||||
c. Format memories into system message string
|
||||
d. Prepend system message to messagesPrompts array
|
||||
e. Return { memories, messagesPrompts }
|
||||
3. Create underlying LLM via Mem0ClassSelector.createProvider()
|
||||
4. Call model.doGenerate(updatedOptions) or model.doStream(updatedOptions)
|
||||
5. Return result
|
||||
```
|
||||
|
||||
**Critical detail:** The `addMemories` call in step 2a is **NON-BLOCKING**. It uses `.then().catch()` without `await`, meaning:
|
||||
- Memory storage happens asynchronously in the background
|
||||
- The LLM response is not delayed by the memory write
|
||||
- If the memory write fails, it logs an error but does not affect the response
|
||||
- There is a brief window where the latest conversation is not yet stored
|
||||
|
||||
### Memory injection format
|
||||
|
||||
The memories are injected as a system message at position 0 of the prompt array:
|
||||
|
||||
```typescript
|
||||
{
|
||||
role: "system",
|
||||
content: "System Message: These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n Memory: ... \n\n Memory: ... \n\n"
|
||||
}
|
||||
```
|
||||
|
||||
## 10. Custom Configuration
|
||||
|
||||
### Custom Mem0 API host
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({
|
||||
mem0Config: {
|
||||
host: "https://my-mem0-instance.example.com",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Or with standalone utilities:
|
||||
|
||||
```typescript
|
||||
const memories = await retrieveMemories(prompt, {
|
||||
user_id: "alice",
|
||||
host: "https://my-mem0-instance.example.com",
|
||||
});
|
||||
```
|
||||
|
||||
### Organization and project scoping
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0();
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", {
|
||||
user_id: "alice",
|
||||
org_id: "org-123",
|
||||
project_id: "proj-456",
|
||||
}),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
|
||||
Note: `org_id` takes precedence over `org_name`. If `org_id` is set, `org_name` and `project_name` are not sent in the request.
|
||||
|
||||
### Memory filtering and ranking
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0();
|
||||
const model = mem0("gpt-4-turbo", {
|
||||
user_id: "alice",
|
||||
top_k: 10, // retrieve up to 10 memories (default: 5)
|
||||
threshold: 0.8, // only memories with score >= 0.8
|
||||
rerank: true, // enable re-ranking of results
|
||||
filter_memories: true,
|
||||
});
|
||||
```
|
||||
|
||||
### Provider-specific configuration
|
||||
|
||||
Pass SDK-specific settings via the `config` field:
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({
|
||||
provider: "openai",
|
||||
config: {
|
||||
organization: "org-xxx",
|
||||
project: "proj-xxx",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Default Mem0 config for all calls
|
||||
|
||||
Set defaults at the provider level that apply to every model created:
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0({
|
||||
mem0Config: {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
top_k: 10,
|
||||
},
|
||||
});
|
||||
|
||||
// These calls inherit user_id, enable_graph, and top_k from mem0Config
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo"),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
|
||||
Per-call settings (passed as the second argument to `mem0()`) are merged on top of `mem0Config`, so you can override specific fields:
|
||||
|
||||
```typescript
|
||||
// Override user_id for this specific call
|
||||
const model = mem0("gpt-4-turbo", { user_id: "bob" });
|
||||
```
|
||||
|
||||
The merge order is: `config.mem0Config` (provider defaults) < `settings` (per-call overrides).
|
||||
Reference in New Issue
Block a user