feat: add filesystem demo with file upload and streaming

- Add example demonstrating file upload to Letta data sources
- Include text file upload from disk and string creation
- Add PDF download and upload functionality
- Implement streaming agent responses with interactive chat
- Show how to attach data sources to agents
This commit is contained in:
Cameron Pfiffer
2025-07-30 10:47:10 -07:00
parent 5d80059746
commit 5d8019684d
3 changed files with 226 additions and 0 deletions

34
examples/files/README.md Normal file
View File

@@ -0,0 +1,34 @@
# Letta Files and Streaming Demo
This demo shows how to work with Letta's file upload and streaming capabilities.
## Features
- Upload files from disk to a Letta data source
- Create files from strings and upload them
- Download and upload PDF files
- Create an agent and attach data sources
- Stream agent responses in real-time
- Interactive chat with file-aware agent
## Files
- `main.py` - Main demo script showing file upload and streaming
- `example-on-disk.txt` - Sample text file for upload demonstration
- `memgpt.pdf` - MemGPT paper (downloaded automatically)
## Setup
1. Set your Letta API key: `export LETTA_API_KEY=your_key_here`
2. Install dependencies: `pip install letta-client requests rich`
3. Run the demo: `python main.py`
## Usage
The demo will:
1. Create a data source called "Example Source"
2. Upload the example text file and PDF
3. Create an agent named "Clippy"
4. Start an interactive chat session
Type 'quit' or 'exit' to end the conversation.

View File

@@ -0,0 +1,2 @@
Hey, you're looking at a different example.
This password is "stateful agents".

190
examples/files/main.py Normal file
View File

@@ -0,0 +1,190 @@
"""
Letta Filesystem
This demo shows how to:
1. Create a folder and upload files (both from disk and from strings)
2. Create an agent and attach the data folder
3. Stream the agent's responses
4. Query the agent about the uploaded files
The demo uploads:
- A text file from disk (example-on-disk.txt)
- A text file created from a string (containing a password)
- The MemGPT paper PDF from arXiv
Then asks the agent to summarize the paper and find passwords in the files.
"""
from letta_client import Letta
from letta_client.core.api_error import ApiError
import os
import requests
from rich import print
LETTA_API_KEY = os.getenv("LETTA_API_KEY")
if LETTA_API_KEY is None:
raise ValueError("LETTA_API_KEY is not set")
FOLDER_NAME = "Example Folder"
# Connect to our Letta server
client = Letta(token=LETTA_API_KEY)
# get an available embedding_config
embedding_configs = client.embedding_models.list()
embedding_config = embedding_configs[0]
# Check if the folder already exists
try:
folder_id = client.folders.retrieve_by_name(FOLDER_NAME)
# We got an API error. Check if it's a 404, meaning the folder doesn't exist.
except ApiError as e:
if e.status_code == 404:
# Create a new folder
folder = client.folders.create(
name=FOLDER_NAME,
description="This is an example folder",
instructions="Use this data folder to see how Letta works.",
)
folder_id = folder.id
else:
raise e
except Exception as e:
# Something else went wrong
raise e
#
# There's two ways to upload a file to a folder.
#
# 1. From an existing file
# 2. From a string by encoding it into a base64 string
#
#
# 1. From an existing file
# "rb" means "read binary"
file = open("example-on-disk.txt", "rb")
# Upload the file to the folder
file = client.folders.files.upload(
folder_id=folder_id,
file=file,
duplicate_handling="skip"
)
# 2. From a string by encoding it into a base64 string
import io
content = """
This is an example file. If you can read this,
the password is 'letta'.
"""
# Encode the string into bytes, and then create a file-like object
# that exists only in memory.
file_object = io.BytesIO(content.encode("utf-8"))
# Set the name of the file
file_object.name = "example.txt"
# Upload the file to the folder
file = client.folders.files.upload(
folder_id=folder_id,
file=file_object,
duplicate_handling="skip"
)
#
# You can also upload PDFs!
# Letta extracts text from PDFs using OCR.
#
# Download the PDF to the local directory if it doesn't exist
if not os.path.exists("memgpt.pdf"):
# Download the PDF
print("Downloading memgpt.pdf")
response = requests.get("https://arxiv.org/pdf/2310.08560")
with open("memgpt.pdf", "wb") as f:
f.write(response.content)
# Upload the PDF to the folder
file = client.folders.files.upload(
folder_id=folder_id,
file=open("memgpt.pdf", "rb"),
duplicate_handling="skip"
)
#
# Now we need to create an agent that can use this folder
#
# Create an agent
agent = client.agents.create(
model="openai/gpt-4o-mini",
name="Example Agent",
description="This agent looks at files and answers questions about them.",
memory_blocks = [
{
"label": "human",
"value": "The human wants to know about the files."
},
{
"label": "persona",
"value": "My name is Clippy, I answer questions about files."
}
]
)
# Attach the data folder to the agent.
# Once the folder is attached, the agent will be able to see all
# files in the folder.
client.agents.folders.attach(
agent_id=agent.id,
folder_id=folder_id
)
########################################################
# This code makes a simple chatbot interface to the agent
########################################################
# Wrap this in a try/catch block to remove the agent in the event of an error
try:
print(f"🤖 Connected to agent: {agent.name}")
print("💡 Type 'quit' or 'exit' to end the conversation")
print("=" * 50)
while True:
# Get user input
try:
user_input = input("\n👤 You: ").strip()
except (EOFError, KeyboardInterrupt):
print("\n👋 Goodbye!")
break
if user_input.lower() in ['quit', 'exit', 'q']:
print("👋 Goodbye!")
break
if not user_input:
continue
# Stream the agent's response
stream = client.agents.messages.create_stream(
agent_id=agent.id,
messages=[
{
"role": "user",
"content": user_input
}
],
)
for chunk in stream:
print(chunk)
finally:
client.agents.delete(agent.id)