Custom instructions API improvements (#2140)

Co-authored-by: Deshraj Yadav <deshrajdry@gmail.com>
This commit is contained in:
Dev Khant
2025-01-15 05:54:23 +05:30
committed by GitHub
parent 3fa4b80deb
commit 82359774b7
4 changed files with 103 additions and 236 deletions

View File

@@ -56,10 +56,24 @@ Here's how to set custom categories:
```python Code
# Update custom categories
new_categories = [
{"cooking": "For users interested in cooking and culinary experiences"},
{"fitness": "Content related to fitness and exercise"}
{
"cooking": "For users interested in cooking and culinary experiences. Includes recipes, cooking tips, meal prep ideas, healthy eating guides, kitchen hacks, and recommendations for cooking tools or ingredients."
},
{
"gym": "Captures all the gym and workout-related content. Includes fitness plans, weightlifting techniques, cardio routines, yoga practices, recovery tips, and recommendations for gym equipment or supplements."
},
{
"office-work": "Includes all the work-related content, focusing on productivity tips, team collaboration strategies, email management, remote work setup advice, time management techniques, and tools for boosting efficiency in a professional setting."
},
{
"personal-life": "Includes all the personal life-related content, such as self-care routines, relationship advice, mindfulness practices, hobbies, life goals, and tips for maintaining a work-life balance."
},
{
"cricket": "Captures all the cricket-related content. Includes match analysis, player statistics, tournament schedules, game highlights, tips for playing cricket, and updates on domestic and international cricket leagues."
}
]
response = client.update_custom_instructions_and_categories({"custom_categories": new_categories})
response = client.update_project(custom_categories=new_categories)
print(response)
```
@@ -79,17 +93,31 @@ from mem0 import MemoryClient
client = MemoryClient(api_key="xxx")
# Get current custom categories
categories = client.get_custom_instructions_and_categories(["custom_categories"])
categories = client.get_project(fields=["custom_categories"])
print(categories)
```
```json Output
{
"custom_categories": [
{"cooking": "For users interested in cooking and culinary experiences"},
{"fitness": "Content related to fitness and exercise"}
{
"cooking": "For users interested in cooking and culinary experiences. Includes recipes, cooking tips, meal prep ideas, healthy eating guides, kitchen hacks, and recommendations for cooking tools or ingredients."
},
{
"gym": "Captures all the gym and workout-related content. Includes fitness plans, weightlifting techniques, cardio routines, yoga practices, recovery tips, and recommendations for gym equipment or supplements."
},
{
"office-work": "Includes all the work-related content, focusing on productivity tips, team collaboration strategies, email management, remote work setup advice, time management techniques, and tools for boosting efficiency in a professional setting."
},
{
"personal-life": "Includes all the personal life-related content, such as self-care routines, relationship advice, mindfulness practices, hobbies, life goals, and tips for maintaining a work-life balance."
},
{
"cricket": "Captures all the cricket-related content. Includes match analysis, player statistics, tournament schedules, game highlights, tips for playing cricket, and updates on domestic and international cricket leagues."
}
]
}
```
</CodeGroup>

View File

@@ -23,15 +23,30 @@ You can set custom instructions for your project using the following method:
```python Code
# Update custom instructions
prompt ="""
Your task is to extract ONLY health-related information from conversations, including:
Your Task: Extract ONLY health-related information from conversations, focusing on the following areas:
- Medical conditions, symptoms, diagnoses
- Medications, treatments, procedures
- Diet, exercise, sleep habits
- Doctor visits and appointments
- Health metrics (weight, blood pressure, etc)
1. Medical Conditions, Symptoms, and Diagnoses:
- Illnesses, disorders, or symptoms (e.g., fever, diabetes).
- Confirmed or suspected diagnoses.
2. Medications, Treatments, and Procedures:
- Prescription or OTC medications (names, dosages).
- Treatments, therapies, or medical procedures.
3. Diet, Exercise, and Sleep:
- Dietary habits, fitness routines, and sleep patterns.
4. Doctor Visits and Appointments:
- Past, upcoming, or regular medical visits.
5. Health Metrics:
- Data like weight, BP, cholesterol, or sugar levels.
Guidelines:
- Focus solely on health-related content.
- Maintain clarity and context accuracy while recording.
"""
response = client.update_custom_instructions_and_categories({"custom_instructions": prompt})
response = client.update_project(custom_instructions=prompt)
print(response)
```
@@ -47,13 +62,13 @@ You can also retrieve the current custom instructions:
<CodeGroup>
```python Code
# Retrieve current custom instructions
response = client.get_custom_instructions_and_categories(["custom_instructions"])
response = client.update_project(fields=["custom_instructions"])
print(response)
```
```json Output
{
"custom_instructions": "Your task is to extract ONLY health-related information from conversations, including:\n\n- Medical conditions, symptoms, diagnoses\n- Medications, treatments, procedures\n- Diet, exercise, sleep habits\n- Doctor visits and appointments\n- Health metrics (weight, blood pressure, etc)"
"custom_instructions": "Your Task: Extract ONLY health-related information from conversations, focusing on the following areas:\n1. Medical Conditions, Symptoms, and Diagnoses - illnesses, disorders, or symptoms (e.g., fever, diabetes), confirmed or suspected diagnoses.\n2. Medications, Treatments, and Procedures - prescription or OTC medications (names, dosages), treatments, therapies, or medical procedures.\n3. Diet, Exercise, and Sleep - dietary habits, fitness routines, and sleep patterns.\n4. Doctor Visits and Appointments - past, upcoming, or regular medical visits.\n5. Health Metrics - data like weight, BP, cholesterol, or sugar levels.\n\nGuidelines: Focus solely on health-related content. Maintain clarity and context accuracy while recording."
}
```
</CodeGroup>

View File

@@ -4056,197 +4056,6 @@
}
]
}
},
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/": {
"get": {
"tags": ["custom-instructions-and-categories"],
"summary": "Get custom instructions and categories",
"description": "Retrieve custom categories and instructions for a specific project",
"operationId": "get_custom_instructions_and_categories",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Organization ID"
},
{
"name": "project_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Project ID"
}
],
"responses": {
"200": {
"description": "Successfully retrieved custom instructions and categories",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"custom_categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of custom categories for the project"
},
"custom_instructions": {
"type": "string",
"description": "Custom instructions text for the project"
}
},
"required": ["custom_categories", "custom_instructions"]
}
}
}
},
"403": {
"description": "Unauthorized access",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unauthorized to modify custom instructions and categories."
}
}
}
}
}
}
},
"x-code-samples": [
{
"lang": "Python",
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/\"\nheaders = {\"Authorization\": \"Token <api-key>\"}\n\nresponse = requests.get(url, headers=headers)\nprint(response.json())"
},
{
"lang": "JavaScript",
"source": "fetch('https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/', {\n headers: {\n 'Authorization': 'Token <api-key>'\n }\n})\n.then(response => response.json())\n.then(data => console.log(data))\n.catch(error => console.error(error));"
}
]
},
"post": {
"tags": ["custom-instructions-and-categories"],
"summary": "Update custom instructions and categories",
"description": "Update custom categories and instructions for a specific project",
"operationId": "update_custom_instructions_and_categories",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Organization ID"
},
{
"name": "project_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Project ID"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"custom_categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of new custom categories for the project"
},
"custom_instructions": {
"type": "string",
"description": "New custom instructions text for the project"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Successfully updated custom instructions and categories",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Updated custom categories / instructions"
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"example": {
"field_name": ["error message"]
}
}
}
}
},
"403": {
"description": "Unauthorized access",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unauthorized to modify custom instructions and categories."
}
}
}
}
}
}
},
"x-code-samples": [
{
"lang": "Python",
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/\"\nheaders = {\n \"Authorization\": \"Token <api-key>\",\n \"Content-Type\": \"application/json\"\n}\npayload = {\n \"custom_categories\": [\"new_category1\", \"new_category2\"],\n \"custom_instructions\": \"New custom instructions text\"\n}\n\nresponse = requests.post(url, headers=headers, json=payload)\nprint(response.json())"
},
{
"lang": "JavaScript",
"source": "fetch('https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/', {\n method: 'POST',\n headers: {\n 'Authorization': 'Token <api-key>',\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n custom_categories: ['new_category1', 'new_category2'],\n custom_instructions: 'New custom instructions text'\n })\n})\n.then(response => response.json())\n.then(data => console.log(data))\n.catch(error => console.error(error));"
}
]
}
}
},
"components": {

View File

@@ -111,6 +111,13 @@ class MemoryClient:
params = self._prepare_params()
response = self.client.get("/v1/ping/", params=params)
response.raise_for_status()
if response.status_code == 200:
data = response.json()
if data.get('org_id') and data.get('project_id'):
self.org_id = data.get('org_id')
self.project_id = data.get('project_id')
except httpx.HTTPStatusError:
raise ValueError("Invalid API Key. Please get a valid API Key from https://app.mem0.ai")
@@ -400,14 +407,14 @@ class MemoryClient:
return response.json()
@api_error_handler
def get_custom_instructions_and_categories(self, fields: List[str]) -> Dict[str, Any]:
def get_project(self, fields: Optional[List[str]]=None) -> Dict[str, Any]:
"""Get instructions or categories for the current project.
Args:
fields: List of field names to retrieve (e.g. ['custom_instructions', 'custom_categories'])
fields: List of fields to retrieve
Returns:
Dictionary containing the requested instructions or categories.
Dictionary containing the requested fields.
Raises:
APIError: If the API request fails.
@@ -418,20 +425,20 @@ class MemoryClient:
params = self._prepare_params({"fields": fields})
response = self.client.get(
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/custom-instructions-and-categories/",
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/",
params=params,
)
response.raise_for_status()
capture_client_event("client.get_custom_instructions_and_categories", self, {"fields": fields})
capture_client_event("client.get_project_details", self, {"fields": fields})
return response.json()
@api_error_handler
def update_custom_instructions_and_categories(self, fields: Dict[str, Any]) -> Dict[str, Any]:
"""Update instructions or categories for the current project.
def update_project(self, custom_instructions: Optional[str]=None, custom_categories: Optional[List[str]]=None) -> Dict[str, Any]:
"""Update the project settings.
Args:
fields: Dictionary of fields to update
(e.g. {"custom_categories": "new instructions", "custom_categories": ["cat1"]})
custom_instructions: New instructions for the project
custom_categories: New categories for the project
Returns:
Dictionary containing the API response.
@@ -443,12 +450,16 @@ class MemoryClient:
if not (self.org_id and self.project_id):
raise ValueError("org_id and project_id must be set to update instructions or categories")
response = self.client.post(
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/custom-instructions-and-categories/",
json=fields,
if custom_instructions is None and custom_categories is None:
raise ValueError("Currently we only support updating custom_instructions or custom_categories, so you must provide at least one of them")
payload = self._prepare_params({"custom_instructions": custom_instructions, "custom_categories": custom_categories})
response = self.client.patch(
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/",
json=payload,
)
response.raise_for_status()
capture_client_event("client.update_custom_instructions_and_categories", self, {"fields": list(fields.keys())})
capture_client_event("client.update_project", self, {"custom_instructions": custom_instructions, "custom_categories": custom_categories})
return response.json()
def chat(self):
@@ -505,17 +516,19 @@ class MemoryClient:
"Note that org_name/project_name are deprecated."
)
# Add org_id and project_id if available
if self.org_id:
# Add org_id and project_id if both are available
if self.org_id and self.project_id:
kwargs["org_id"] = self.org_id
if self.project_id:
kwargs["project_id"] = self.project_id
elif self.org_id or self.project_id:
raise ValueError("Please provide both org_id and project_id")
# Add deprecated org_name and project_name for backward compatibility
if self.organization:
# Add deprecated org_name and project_name if both are available
if self.organization and self.project:
kwargs["org_name"] = self.organization
if self.project:
kwargs["project_name"] = self.project
elif self.organization or self.project:
raise ValueError("Please provide both org_name and project_name")
return {k: v for k, v in kwargs.items() if v is not None}
@@ -731,33 +744,35 @@ class AsyncMemoryClient:
return response.json()
@api_error_handler
async def get_custom_instructions_and_categories(self, fields: List[str]) -> Dict[str, Any]:
async def get_project(self, fields: Optional[List[str]]=None) -> Dict[str, Any]:
if not (self.sync_client.org_id and self.sync_client.project_id):
raise ValueError("org_id and project_id must be set to access instructions or categories")
params = self.sync_client._prepare_params({"fields": fields})
params = self._prepare_params({"fields": fields})
response = await self.async_client.get(
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/custom-instructions-and-categories/",
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/",
params=params,
)
response.raise_for_status()
capture_client_event(
"async_client.get_custom_instructions_and_categories", self.sync_client, {"fields": fields}
"async_client.get_project", self.sync_client, {"fields": fields}
)
return response.json()
@api_error_handler
async def update_custom_instructions_and_categories(self, fields: Dict[str, Any]) -> Dict[str, Any]:
async def update_project(self, custom_instructions: Optional[str], custom_categories: Optional[List[str]]) -> Dict[str, Any]:
if not (self.sync_client.org_id and self.sync_client.project_id):
raise ValueError("org_id and project_id must be set to update instructions or categories")
response = await self.async_client.post(
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/custom-instructions-and-categories/",
json=fields,
payload = self.sync_client._prepare_params({"custom_instructions": custom_instructions, "custom_categories": custom_categories})
response = await self.async_client.patch(
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/",
json=payload,
)
response.raise_for_status()
capture_client_event(
"async_client.update_custom_instructions_and_categories", self.sync_client, {"fields": list(fields.keys())}
"async_client.update_project", self.sync_client, {"custom_instructions": custom_instructions, "custom_categories": custom_categories}
)
return response.json()