docs(skills): refresh mem0 skills against SDK 2.2.1 / TS 3.3.1 (#7548)
This commit is contained in:
@@ -24,7 +24,7 @@ await addMemories(
|
||||
|
||||
```typescript
|
||||
async function addMemories(
|
||||
messages: LanguageModelV2Prompt | string,
|
||||
messages: LanguageModelV3Prompt,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
@@ -33,15 +33,16 @@ async function addMemories(
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `messages` | `LanguageModelV2Prompt \| string` | Messages to store. If a string, wrapped as `[{ role: "user", content: string }]` |
|
||||
| `messages` | `LanguageModelV3Prompt` | Messages to store. A plain string is also handled at runtime (wrapped as `[{ role: "user", content: string }]`) but is not part of the declared type |
|
||||
| `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
|
||||
2. Otherwise, converts `LanguageModelV3Prompt` to Mem0 format via `convertToMem0Format` (maps multimodal parts, but the add endpoint rejects them with a 400)
|
||||
3. Calls `POST {host}/v3/memories/add/` with body `{ messages, user_id?, app_id?, agent_id?, run_id?, metadata?, infer? }` (entity IDs are top-level on add)
|
||||
4. Throws `HTTP error! status: <code>` on a non-2xx response
|
||||
|
||||
**Returns:** The API response from Mem0 (memory operation result).
|
||||
**Returns:** The parsed JSON response from Mem0. The v3 add endpoint queues extraction and responds with `{ status: "PENDING", event_id }` (the provider returns the raw REST JSON, so keys stay snake_case, unlike the `mem0ai` client). With `infer: false` messages are stored verbatim synchronously and the response also includes `results`.
|
||||
|
||||
---
|
||||
|
||||
@@ -63,7 +64,7 @@ const systemPrompt = await retrieveMemories("What restaurants do I like?", {
|
||||
|
||||
```typescript
|
||||
async function retrieveMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
prompt: LanguageModelV3Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<string>;
|
||||
```
|
||||
@@ -72,13 +73,13 @@ async function retrieveMemories(
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `prompt` | `LanguageModelV3Prompt \| 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"`
|
||||
1. Flattens the prompt to a plain string (extracts text from `LanguageModelV3Prompt` parts)
|
||||
2. Calls `searchInternalMemories` (`POST /v3/memories/search/`)
|
||||
3. Accepts either a flat array or a `{ results: [...] }` response and formats each memory as `"Memory: {memory.memory}\n\n"`
|
||||
4. 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.
|
||||
@@ -112,7 +113,7 @@ const memories = await getMemories("What are my preferences?", {
|
||||
|
||||
```typescript
|
||||
async function getMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
prompt: LanguageModelV3Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
@@ -121,21 +122,21 @@ async function getMemories(
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `prompt` | `LanguageModelV3Prompt \| 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 `memories.results` (the array of memory objects)
|
||||
2. Calls `searchInternalMemories` (`POST /v3/memories/search/`)
|
||||
3. Normalizes the response: returns the response itself if it is an array, otherwise `response.results` (or `[]`)
|
||||
|
||||
**Returns:** Memory object array.
|
||||
**Returns:** Flat memory object array.
|
||||
|
||||
---
|
||||
|
||||
## `searchMemories(prompt, config?)`
|
||||
|
||||
Retrieves the **full search API response** including results, relations, scores, and metadata.
|
||||
Retrieves the **raw search API response** including results, scores, and metadata.
|
||||
|
||||
```typescript
|
||||
import { searchMemories } from "@mem0/vercel-ai-provider";
|
||||
@@ -144,14 +145,14 @@ const response = await searchMemories("cooking preferences", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
});
|
||||
// Returns: { results: [{ memory: "...", score: 0.95, ... }], relations: [...] }
|
||||
// Returns: { results: [{ memory: "...", score: 0.95, ... }] }
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
async function searchMemories(
|
||||
prompt: LanguageModelV2Prompt | string,
|
||||
prompt: LanguageModelV3Prompt | string,
|
||||
config?: Mem0ConfigSettings
|
||||
): Promise<any>;
|
||||
```
|
||||
@@ -160,17 +161,17 @@ async function searchMemories(
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `prompt` | `LanguageModelV2Prompt \| string` | The query to search memories for |
|
||||
| `prompt` | `LanguageModelV3Prompt \| 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
|
||||
2. Calls `searchInternalMemories` (`POST /v3/memories/search/`)
|
||||
3. Returns the response without any normalization
|
||||
|
||||
**Returns:** The complete API response object. On error, returns `[]`.
|
||||
**Returns:** The API response as-is (an object with `results`, or a flat array if the API returns one). On error, logs and returns `[]` instead of throwing (unlike the other utilities, which rethrow).
|
||||
|
||||
**Note:** Unlike `getMemories`, this always returns the full response.
|
||||
**Note:** Unlike `getMemories`, this does not unwrap `results`.
|
||||
|
||||
---
|
||||
|
||||
@@ -180,7 +181,7 @@ async function searchMemories(
|
||||
|----------|---------|----------|
|
||||
| `retrieveMemories` | Formatted system prompt **string** | Injecting directly into a `system` parameter for `generateText`/`streamText` |
|
||||
| `getMemories` | Memory **array** | Processing memories programmatically (filtering, transforming, counting) |
|
||||
| `searchMemories` | Full API **response** (results + relations) | Need relations, similarity scores, or complete metadata |
|
||||
| `searchMemories` | Raw API **response** | Need similarity scores or complete metadata |
|
||||
| `addMemories` | API response | Storing new conversation messages as memories |
|
||||
|
||||
## Internal: `searchInternalMemories(query, config?, top_k?)`
|
||||
@@ -191,25 +192,27 @@ Not exported. Used by all retrieval functions.
|
||||
async function searchInternalMemories(
|
||||
query: string,
|
||||
config?: Mem0ConfigSettings,
|
||||
top_k: number = 5
|
||||
top_k: number = 10
|
||||
): Promise<any>;
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
1. Builds a `filters` object from entity identifiers (`user_id`, `app_id`, `agent_id`, `run_id`)
|
||||
2. Resolves entity identifiers
|
||||
3. Loads the API key from `config.mem0ApiKey` or `MEM0_API_KEY` env var
|
||||
4. Calls `POST {host}/v2/memories/search/` with:
|
||||
1. Builds a `filters` object from `config.filters`, then sets `user_id`, `app_id`, `agent_id`, `run_id` on it when present (entity IDs go inside `filters`, never top-level)
|
||||
2. Loads the API key from `config.mem0ApiKey` or `MEM0_API_KEY` env var
|
||||
3. Calls `POST {host}/v3/memories/search/` with:
|
||||
- `query`: the search string
|
||||
- `filters`: the filter object with entity identifiers
|
||||
- `top_k`: from config or default 5
|
||||
- All other config fields spread into the request body
|
||||
- `top_k`: `config.top_k` or default 10 (an explicit `0` is respected)
|
||||
- `threshold`, `rerank`, `metadata`: only when set in config
|
||||
- No other config fields (`infer`, `page`, `page_size`, `host`, `mem0ApiKey`) are sent
|
||||
4. Sends `Authorization: Token <key>` plus `X-Mem0-Source: VERCEL_AI_SDK` and `X-Mem0-Client: mem0-vercel-ai-provider/<version>` headers
|
||||
5. Throws `HTTP error! status: <code>` on a non-2xx response
|
||||
|
||||
**Default host:** `https://api.mem0.ai`
|
||||
|
||||
## Internal: `convertToMem0Format(messages)`
|
||||
|
||||
Not exported. Used by `addMemories` to convert `LanguageModelV2Prompt` messages to Mem0's format.
|
||||
Not exported. Used by `addMemories` to convert `LanguageModelV3Prompt` messages to Mem0's format.
|
||||
|
||||
**Multimodal content mapping:**
|
||||
|
||||
@@ -223,6 +226,8 @@ Not exported. Used by `addMemories` to convert `LanguageModelV2Prompt` messages
|
||||
| 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 } } }` |
|
||||
|
||||
`/v3/memories/add/` rejects structured (non-string) `content` with a 400 `Not a valid string.` (live-tested on the Python SDK with `infer` true and false), so a prompt containing these parts is expected to fail with `HTTP error! status: 400` (checked against the endpoint, not through the provider). Only text parts are storable.
|
||||
|
||||
The function handles three message content shapes:
|
||||
1. **String content**: passed through directly
|
||||
2. **Array content**: each element mapped individually, nulls filtered out
|
||||
@@ -230,7 +235,7 @@ The function handles three message content shapes:
|
||||
|
||||
## Internal: `flattenPrompt(prompt)`
|
||||
|
||||
Not exported. Extracts plain text from `LanguageModelV2Prompt` for use as a search query.
|
||||
Not exported. Extracts plain text from `LanguageModelV3Prompt` for use as a search query.
|
||||
|
||||
- Iterates over prompt parts, extracting text from `user` role messages
|
||||
- For `text` type content: extracts `.text`
|
||||
@@ -249,12 +254,12 @@ All fields are optional. Used across all utility functions.
|
||||
| `agent_id` | `string` | -- | Scope memories to an agent |
|
||||
| `run_id` | `string` | -- | Scope memories to a session/run |
|
||||
| `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 |
|
||||
| `filters` | `Record<string, any>` | -- | Custom search filters (entity IDs above are merged in and win on conflicts) |
|
||||
| `infer` | `boolean` | -- | Sent on add only. `false` stores messages verbatim without extraction |
|
||||
| `page` | `number` | -- | Declared in the type, not sent by the provider |
|
||||
| `page_size` | `number` | -- | Declared in the type, not sent by the provider |
|
||||
| `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 |
|
||||
| `top_k` | `number` | `10` | Number of memories to retrieve |
|
||||
| `threshold` | `number` | -- | Server-side relevance cutoff, not a floor on the returned score; sent only when set |
|
||||
| `rerank` | `boolean` | -- (API default `false`) | Enable re-ranking, sent only when set |
|
||||
| `host` | `string` | `https://api.mem0.ai` | Custom API host |
|
||||
|
||||
@@ -25,26 +25,26 @@ When called with no arguments, defaults to `{ provider: "openai" }`.
|
||||
|
||||
## `Mem0Provider` Interface
|
||||
|
||||
Implements `ProviderV2` from `@ai-sdk/provider`.
|
||||
Implements `ProviderV3` from `@ai-sdk/provider` (`specificationVersion: "v3"`, AI SDK v6).
|
||||
|
||||
```typescript
|
||||
interface Mem0Provider extends ProviderV2 {
|
||||
interface Mem0Provider extends ProviderV3 {
|
||||
// Call directly as a function
|
||||
(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV3;
|
||||
|
||||
// Or use named methods
|
||||
chat(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
completion(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
languageModel(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV2;
|
||||
chat(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV3;
|
||||
completion(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV3;
|
||||
languageModel(modelId: Mem0ChatModelId, settings?: Mem0ChatSettings): LanguageModelV3;
|
||||
}
|
||||
```
|
||||
|
||||
- **Direct call** (`mem0("gpt-5-mini", {...})`): 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).
|
||||
- **`chat()`**: creates a model with `modelType: "chat"`.
|
||||
- **`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`.
|
||||
All three return a `Mem0GenericLanguageModel` instance implementing `LanguageModelV3`.
|
||||
|
||||
## `Mem0ProviderSettings` Interface
|
||||
|
||||
@@ -52,14 +52,14 @@ 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
|
||||
baseURL?: string; // Stored on the model config (default: "https://api.openai.com"), not applied to upstream LLM requests
|
||||
headers?: Record<string, string | undefined>; // Stored on the model config, not applied to upstream 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)
|
||||
fetch?: typeof fetch; // Stored on the model config, not used by the upstream LLM client or Mem0 API calls
|
||||
generateId?: () => string; // Custom ID generator (internal use)
|
||||
name?: string; // Provider instance name
|
||||
modelType?: "completion" | "chat"; // Force model type
|
||||
@@ -75,7 +75,7 @@ interface Mem0ProviderSettings {
|
||||
| `apiKey` | LLM provider API key | `"sk-xxx"` (OpenAI), `"sk-ant-xxx"` (Anthropic) |
|
||||
| `mem0Config` | Default Mem0 settings for all calls | `{ user_id: "alice" }` |
|
||||
| `config` | Provider-specific SDK settings | `{ organization: "org-xxx" }` for OpenAI |
|
||||
| `baseURL` | Override LLM provider base URL | `"https://my-proxy.example.com"` |
|
||||
| `config.baseURL` | Override LLM provider base URL (put it inside `config`; the top-level `baseURL` does not reach the upstream client) | `{ baseURL: "https://my-proxy.example.com/v1" }` |
|
||||
|
||||
## `mem0` Singleton
|
||||
|
||||
@@ -94,7 +94,7 @@ 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.
|
||||
Configuration for memory operations. Used as `Mem0ChatSettings` (per-call) or `Mem0Config` (provider-level default; same shape, not exported from the package entry point). All fields are optional.
|
||||
|
||||
```typescript
|
||||
interface Mem0ConfigSettings {
|
||||
@@ -104,13 +104,13 @@ interface Mem0ConfigSettings {
|
||||
run_id?: string; // Scope memories to a specific run/session
|
||||
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
|
||||
infer?: boolean; // Sent on add only: false stores messages verbatim without extraction
|
||||
page?: number; // Declared in the type, not sent by the provider
|
||||
page_size?: number; // Declared in the type, not sent by the provider
|
||||
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 (default: 0.1)
|
||||
rerank?: boolean; // Enable re-ranking of search results (default: false)
|
||||
top_k?: number; // Number of memories to retrieve (default: 10)
|
||||
threshold?: number; // Server-side relevance cutoff; sent only when set
|
||||
rerank?: boolean; // Enable re-ranking of search results; sent only when set (API default: false)
|
||||
host?: string; // Custom Mem0 API host (default: "https://api.mem0.ai")
|
||||
}
|
||||
```
|
||||
@@ -137,17 +137,18 @@ mem0("gpt-5-mini", { user_id: "alice" })
|
||||
|
||||
## `LLMProviderSettings` Type
|
||||
|
||||
Union of provider-specific settings. Extends all supported provider setting interfaces:
|
||||
Union of provider-specific settings for all supported provider SDKs:
|
||||
|
||||
```typescript
|
||||
interface LLMProviderSettings extends
|
||||
OpenAIProviderSettings,
|
||||
AnthropicProviderSettings,
|
||||
CohereProviderSettings,
|
||||
GroqProviderSettings {}
|
||||
type LLMProviderSettings =
|
||||
| OpenAIProviderSettings
|
||||
| AnthropicProviderSettings
|
||||
| CohereProviderSettings
|
||||
| GroqProviderSettings
|
||||
| GoogleGenerativeAIProviderSettings;
|
||||
```
|
||||
|
||||
Pass via the `config` field of `Mem0ProviderSettings` to forward settings to the underlying LLM provider SDK.
|
||||
Pass via the `config` field of `Mem0ProviderSettings` to forward settings (e.g., `baseURL`, `headers`, `apiKey`) to the underlying LLM provider SDK. `config` is spread after `apiKey`, so a `config.apiKey` takes precedence.
|
||||
|
||||
## Provider Selection: `Mem0ClassSelector`
|
||||
|
||||
@@ -155,12 +156,12 @@ Internal class that maps the `provider` string to the correct AI SDK provider.
|
||||
|
||||
```typescript
|
||||
class Mem0ClassSelector {
|
||||
static supportedProviders = ["openai", "anthropic", "cohere", "groq", "google"];
|
||||
static supportedProviders = ["openai", "anthropic", "cohere", "groq", "google", "gemini"];
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**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.
|
||||
`"gemini"` is an alias of `"google"` (both map to `createGoogleGenerativeAI`). Any other value throws `"Model not supported: <value>"`.
|
||||
|
||||
### Provider mapping
|
||||
|
||||
@@ -170,7 +171,7 @@ class Mem0ClassSelector {
|
||||
| `"anthropic"` | `@ai-sdk/anthropic` | `createAnthropic` |
|
||||
| `"cohere"` | `@ai-sdk/cohere` | `createCohere` |
|
||||
| `"groq"` | `@ai-sdk/groq` | `createGroq` |
|
||||
| `"google"` | `@ai-sdk/google` | `createGoogleGenerativeAI` |
|
||||
| `"google"` or `"gemini"` | `@ai-sdk/google` | `createGoogleGenerativeAI` |
|
||||
|
||||
## `Mem0` Facade Class
|
||||
|
||||
@@ -184,7 +185,7 @@ const chatModel = mem0.chat("gpt-5-mini", { user_id: "alice" });
|
||||
const completionModel = mem0.completion("gpt-5-mini");
|
||||
```
|
||||
|
||||
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.
|
||||
The facade defaults its base URL to `"https://api.openai.com"`. It always uses `"openai"` as the provider for created models, and only stores `baseURL` and `headers` from its options: the `provider`, `mem0ApiKey`, and `apiKey` options are ignored, so `MEM0_API_KEY` and `OPENAI_API_KEY` must come from the environment. Prefer `createMem0` for anything beyond a quick start.
|
||||
|
||||
**Methods:**
|
||||
- `chat(modelId, settings?)` -- creates a model with `modelType: "chat"`
|
||||
@@ -192,13 +193,11 @@ The facade defaults its base URL to `"http://127.0.0.1:11434/api"` (Ollama-style
|
||||
|
||||
## `Mem0GenericLanguageModel` Class
|
||||
|
||||
The core class implementing `LanguageModelV2`. Created by `createMem0` or the `Mem0` facade.
|
||||
The core class implementing `LanguageModelV3`. Created by `createMem0` or the `Mem0` facade.
|
||||
|
||||
```typescript
|
||||
class Mem0GenericLanguageModel implements LanguageModelV2 {
|
||||
readonly specificationVersion = "v2";
|
||||
readonly defaultObjectGenerationMode = "json";
|
||||
readonly supportsImageUrls = false;
|
||||
class Mem0GenericLanguageModel implements LanguageModelV3 {
|
||||
readonly specificationVersion = "v3";
|
||||
readonly supportedUrls: Record<string, RegExp[]> = { '*': [/.*/] };
|
||||
|
||||
provider: string; // e.g., "openai"
|
||||
@@ -206,22 +205,26 @@ class Mem0GenericLanguageModel implements LanguageModelV2 {
|
||||
settings: Mem0ChatSettings;
|
||||
config: Mem0ChatConfig;
|
||||
|
||||
async doGenerate(options: LanguageModelV2CallOptions): Promise<...>;
|
||||
async doStream(options: LanguageModelV2CallOptions): Promise<...>;
|
||||
async doGenerate(options: LanguageModelV3CallOptions): Promise<...>;
|
||||
async doStream(options: LanguageModelV3CallOptions): Promise<...>;
|
||||
}
|
||||
```
|
||||
|
||||
`defaultObjectGenerationMode` and `supportsImageUrls` (V2 properties) no longer exist.
|
||||
|
||||
Both `doGenerate` and `doStream` follow the same internal flow:
|
||||
|
||||
1. Build `Mem0ConfigSettings` from `config.mem0Config` merged with `settings`
|
||||
1. Build `Mem0ConfigSettings` from `config.mem0ApiKey`, then `config.mem0Config`, then `settings` (later entries win)
|
||||
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
|
||||
- Await `addMemories` (errors are logged and ignored)
|
||||
- Await `getMemories` to retrieve relevant memories (on failure, continue with no memories)
|
||||
- If any memories were found, format them as a system message and prepend it to a copy of the prompt
|
||||
3. Create the underlying LLM model via `Mem0ClassSelector`
|
||||
4. Delegate to the underlying model's `doGenerate` or `doStream`
|
||||
5. Return the result
|
||||
|
||||
`doGenerate` additionally appends a `source` content part (`title: "Mem0 Memories"`) with `providerMetadata.mem0.memories` and `providerMetadata.mem0.memoriesText` when memories were retrieved. `doStream` returns the underlying stream result unchanged (no Mem0 source) and throws `"Streaming failed or method not implemented."` if streaming setup fails.
|
||||
|
||||
**Note:** Entity identifier fields use snake_case (`user_id`, `app_id`, `agent_id`, `run_id`) to match the Mem0 API.
|
||||
|
||||
## Type: `Mem0ChatModelId`
|
||||
@@ -230,4 +233,4 @@ Both `doGenerate` and `doStream` follow the same internal flow:
|
||||
type Mem0ChatModelId = string & NonNullable<unknown>;
|
||||
```
|
||||
|
||||
Any non-null string. The model ID is passed through to the underlying provider (e.g., `"gpt-5-mini"`, `"gemini-pro"`).
|
||||
Any non-null string. The model ID is passed through to the underlying provider (e.g., `"gpt-5-mini"`, `"gemini-2.5-flash"`).
|
||||
|
||||
@@ -20,7 +20,7 @@ const { text } = await generateText({
|
||||
console.log(text);
|
||||
```
|
||||
|
||||
Memories are automatically retrieved before the call and stored after.
|
||||
The prompt is stored to Mem0 and relevant memories are retrieved before the LLM call (see section 8).
|
||||
|
||||
## 2. Wrapped Model with streamText (Streaming)
|
||||
|
||||
@@ -42,7 +42,7 @@ for await (const chunk of result.textStream) {
|
||||
}
|
||||
```
|
||||
|
||||
Memory retrieval happens before streaming begins. The conversation is stored to Mem0 as a fire-and-forget call (non-blocking).
|
||||
The add request and the memory search both finish before streaming begins (extraction itself is async). The Mem0 source (`sources`) is only attached by `generateText`, not by streaming.
|
||||
|
||||
## 3. Standalone Utilities with OpenAI
|
||||
|
||||
@@ -136,7 +136,7 @@ console.log(object);
|
||||
// { breakfast: "Avocado toast (you mentioned loving it)", lunch: "...", ... }
|
||||
```
|
||||
|
||||
The `defaultObjectGenerationMode` is `"json"`, so structured output works out of the box.
|
||||
The wrapped model forwards all call options (including the response format) to the underlying provider, so structured output works out of the box. `generateObject` is deprecated in AI SDK v6 in favor of `generateText` with `output: Output.object({ schema })`; both go through the same wrapped model.
|
||||
|
||||
## 6. Multi-Provider Setup
|
||||
|
||||
@@ -195,22 +195,20 @@ 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 { convertToModelMessages, streamText, UIMessage } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, user_id } = await req.json();
|
||||
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
const { messages, user_id }: { messages: UIMessage[]; user_id: string } = await req.json();
|
||||
|
||||
const result = streamText({
|
||||
model: mem0("gpt-5-mini", { user_id }),
|
||||
prompt: lastMessage.content,
|
||||
messages: await convertToModelMessages(messages),
|
||||
});
|
||||
|
||||
return result.toDataStreamResponse();
|
||||
return result.toUIMessageStreamResponse();
|
||||
}
|
||||
```
|
||||
|
||||
@@ -219,22 +217,25 @@ export async function POST(req: Request) {
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import { streamText } from "ai";
|
||||
import { convertToModelMessages, streamText, UIMessage } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, user_id } = await req.json();
|
||||
const { messages, user_id }: { messages: UIMessage[]; user_id: string } = await req.json();
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
const lastText = lastMessage.parts
|
||||
.flatMap((part) => (part.type === "text" ? [part.text] : []))
|
||||
.join(" ");
|
||||
|
||||
// Retrieve relevant memories
|
||||
const memories = await retrieveMemories(lastMessage.content, {
|
||||
const memories = await retrieveMemories(lastText, {
|
||||
user_id,
|
||||
});
|
||||
|
||||
// Stream the response
|
||||
const result = streamText({
|
||||
model: openai("gpt-5-mini"),
|
||||
prompt: lastMessage.content,
|
||||
messages: await convertToModelMessages(messages),
|
||||
system: memories,
|
||||
});
|
||||
|
||||
@@ -242,14 +243,14 @@ export async function POST(req: Request) {
|
||||
result.text.then(async (text) => {
|
||||
await addMemories(
|
||||
[
|
||||
{ role: "user", content: [{ type: "text", text: lastMessage.content }] },
|
||||
{ role: "user", content: [{ type: "text", text: lastText }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
{ user_id }
|
||||
);
|
||||
});
|
||||
|
||||
return result.toDataStreamResponse();
|
||||
return result.toUIMessageStreamResponse();
|
||||
}
|
||||
```
|
||||
|
||||
@@ -260,25 +261,26 @@ export async function POST(req: Request) {
|
||||
```
|
||||
1. doGenerate(options) or doStream(options) is called
|
||||
2. processMemories(messagesPrompts, mem0Config):
|
||||
a. addMemories(messagesPrompts, mem0Config)
|
||||
--> fire-and-forget: .then().catch(), NO await
|
||||
a. await addMemories(messagesPrompts, mem0Config)
|
||||
--> POST /v3/memories/add/ with converted messages
|
||||
--> errors are caught and logged
|
||||
b. await getMemories(messagesPrompts, mem0Config)
|
||||
--> POST /v3/memories/search/ with flattened prompt
|
||||
--> returns memory array
|
||||
c. Format memories into system message string
|
||||
d. Prepend system message to messagesPrompts array
|
||||
d. If memories were found, prepend the system message to a copy of messagesPrompts
|
||||
e. Return { memories, messagesPrompts }
|
||||
3. Create underlying LLM via Mem0ClassSelector.createProvider()
|
||||
4. Call model.doGenerate(updatedOptions) or model.doStream(updatedOptions)
|
||||
5. Return result
|
||||
5. doGenerate appends the "Mem0 Memories" source when memories were found
|
||||
6. 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
|
||||
**Critical detail:** The `addMemories` call in step 2a is **awaited**, meaning:
|
||||
- The add request is sent (and awaited) before the search and the LLM call, but extraction is async (`/v3/memories/add/` only queues the work and returns `PENDING`), so facts from the current prompt are usually not searchable until a later call
|
||||
- Each wrapped call adds one Mem0 write and one Mem0 search of latency before the LLM starts
|
||||
- If the memory write fails, it logs an error and the call continues
|
||||
- `messagesPrompts` is the full prompt (all roles, including earlier turns), so every call sends the entire conversation to the add endpoint
|
||||
|
||||
### Memory injection format
|
||||
|
||||
@@ -318,8 +320,8 @@ const memories = await retrieveMemories(prompt, {
|
||||
const mem0 = createMem0();
|
||||
const model = mem0("gpt-5-mini", {
|
||||
user_id: "alice",
|
||||
top_k: 10, // retrieve up to 10 memories (default: 5)
|
||||
threshold: 0.8, // only memories with score >= 0.8
|
||||
top_k: 20, // retrieve up to 20 memories (default: 10)
|
||||
threshold: 0.8, // server-side cutoff applied before score blending
|
||||
rerank: true, // enable re-ranking of results
|
||||
});
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user