Skip to content
Closed
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
76 changes: 76 additions & 0 deletions examples/memory/memory.add.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Example: Add text directly to memory

1. Run memory.create.py first to create a memory.
2. Add your API key to the environment variables or replace it in the code.
"""

import os

from langbase import Langbase

# Initialize the Langbase client
langbase = Langbase(api_key=os.getenv("LANGBASE_API_KEY"))


def main():
try:
# Basic text addition
print("📝 Adding basic text to memory...")
basic_result = langbase.memories.add(
memory_name="my-knowledge-base",
text="This is important information about machine learning fundamentals. "
"It covers supervised learning, unsupervised learning, and reinforcement learning concepts.",
)
print(f"✅ Basic text added: {basic_result['document_name']}")

# Text addition with custom name and metadata
print("\n📝 Adding detailed text with metadata...")
detailed_result = langbase.memories.add(
memory_name="my-knowledge-base",
text="Deep learning is a subset of machine learning that uses artificial neural networks "
"with multiple layers to model and understand complex patterns in data. It has "
"revolutionized fields like computer vision, natural language processing, and speech recognition.",
document_name="deep-learning-intro",
metadata={
"category": "machine-learning",
"topic": "deep-learning",
"difficulty": "intermediate",
"source": "manual-entry",
},
)
print(f"✅ Detailed text added: {detailed_result['document_name']}")

# Multiple text entries
texts = [
{
"text": "Supervised learning uses labeled training data to learn a mapping from inputs to outputs.",
"document_name": "supervised-learning",
"metadata": {"type": "definition", "category": "ml-concepts"},
},
{
"text": "Unsupervised learning finds hidden patterns in data without using labeled examples.",
"document_name": "unsupervised-learning",
"metadata": {"type": "definition", "category": "ml-concepts"},
},
{
"text": "Reinforcement learning learns optimal actions through trial and error interactions with an environment.",
"document_name": "reinforcement-learning",
"metadata": {"type": "definition", "category": "ml-concepts"},
},
]

print("\n📝 Adding multiple texts...")
for item in texts:
result = langbase.memories.add(memory_name="my-knowledge-base", **item)
print(f"✅ Added: {result['document_name']}")

print("\n🎉 All texts have been added to the memory!")
print("You can now query this memory to retrieve relevant information.")

except Exception as error:
print(f"❌ Error: {error}")


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions langbase/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
MEMORY_DOCUMENTS_ENDPOINT = "/v1/memory/{memory_name}/documents"
MEMORY_DOCUMENT_DETAIL_ENDPOINT = "/v1/memory/{memory_name}/documents/{document_name}"
MEMORY_DOCUMENTS_UPLOAD_ENDPOINT = "/v1/memory/documents"
MEMORY_TEXT_ADD_ENDPOINT = "/v1/memory/text"
MEMORY_DOCUMENT_EMBEDDINGS_RETRY_ENDPOINT = (
"/v1/memory/{memory_name}/documents/{document_name}/embeddings/retry"
)
Expand Down
29 changes: 29 additions & 0 deletions langbase/primitives/memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
MEMORY_DOCUMENTS_UPLOAD_ENDPOINT,
MEMORY_ENDPOINT,
MEMORY_RETRIEVE_ENDPOINT,
MEMORY_TEXT_ADD_ENDPOINT,
)
from langbase.errors import APIError, create_api_error
from langbase.types import (
ContentType,
EmbeddingModel,
MemoryAddTextResponse,
MemoryCreateResponse,
MemoryDeleteDocResponse,
MemoryDeleteResponse,
Expand Down Expand Up @@ -250,3 +252,30 @@ def list(self) -> List[MemoryListResponse]:
List of memory objects
"""
return self.request.get(MEMORY_ENDPOINT)

def add(
self,
memory_name: str,
text: str,
document_name: Optional[str] = None,
metadata: Optional[Dict[str, str]] = None,
) -> MemoryAddTextResponse:
"""
Add text directly to a memory without file upload.

Args:
memory_name: Name of the memory to add text to
text: Text content to add to the memory
document_name: Optional custom document name
metadata: Optional metadata for the text document

Returns:
Text addition response
"""
options = {
"memoryName": memory_name,
"text": text,
"documentName": document_name,
"metadata": metadata,
}
return self.request.post(MEMORY_TEXT_ADD_ENDPOINT, clean_null_values(options))
9 changes: 9 additions & 0 deletions langbase/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,15 @@ class MemoryRetryDocEmbedResponse(BaseDeleteResponse):
pass


class MemoryAddTextResponse(TypedDict):
"""Response from adding text to memory."""

document_name: str
status: Literal["queued"]
memory_name: str
url: str


class MemoryRetrieveResponse(TypedDict):
"""Response from retrieving from memory."""

Expand Down
75 changes: 75 additions & 0 deletions tests/test_memories.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
MEMORY_DOCUMENTS_UPLOAD_ENDPOINT,
MEMORY_ENDPOINT,
MEMORY_RETRIEVE_ENDPOINT,
MEMORY_TEXT_ADD_ENDPOINT,
)
from langbase.types import (
MemoryAddTextResponse,
MemoryCreateResponse,
MemoryDeleteResponse,
MemoryListDocResponse,
Expand Down Expand Up @@ -265,3 +267,76 @@ def test_documents_embeddings_retry(self, langbase_client, mock_responses):
assert len(responses.calls) == 1
request = responses.calls[0].request
validate_response_headers(request.headers, AUTH_AND_JSON_CONTENT_HEADER)

@responses.activate
def test_memories_add_text_minimal(self, langbase_client):
"""Test memories.add method with minimal parameters."""
memory_name = "test-memory"
text = "This is a test text to add to memory."

expected_response = {
"document_name": "text-2024-08-21T10-30-45.txt",
"status": "queued",
"memory_name": memory_name,
"url": f"https://langbase.com/memory/user/{memory_name}",
}

responses.add(
responses.POST,
f"{BASE_URL}{MEMORY_TEXT_ADD_ENDPOINT}",
json=expected_response,
status=200,
)

result = langbase_client.memories.add(memory_name=memory_name, text=text)

assert result == expected_response
assert len(responses.calls) == 1
request = responses.calls[0].request
validate_response_headers(request.headers, AUTH_AND_JSON_CONTENT_HEADER)

request_json = json.loads(request.body)
assert request_json["memoryName"] == memory_name
assert request_json["text"] == text
assert "documentName" not in request_json
assert "metadata" not in request_json

@responses.activate
def test_memories_add_text_full(self, langbase_client):
"""Test memories.add method with all parameters."""
memory_name = "test-memory"
text = "This is a comprehensive test text with metadata."
document_name = "test-document"
metadata = {"category": "test", "source": "unit-test", "difficulty": "easy"}

expected_response = {
"document_name": f"{document_name}.txt",
"status": "queued",
"memory_name": memory_name,
"url": f"https://langbase.com/memory/user/{memory_name}",
}

responses.add(
responses.POST,
f"{BASE_URL}{MEMORY_TEXT_ADD_ENDPOINT}",
json=expected_response,
status=200,
)

result = langbase_client.memories.add(
memory_name=memory_name,
text=text,
document_name=document_name,
metadata=metadata,
)

assert result == expected_response
assert len(responses.calls) == 1
request = responses.calls[0].request
validate_response_headers(request.headers, AUTH_AND_JSON_CONTENT_HEADER)

request_json = json.loads(request.body)
assert request_json["memoryName"] == memory_name
assert request_json["text"] == text
assert request_json["documentName"] == document_name
assert request_json["metadata"] == metadata