Simple Chat App with Memory
Build a basic chat application with persistent memory using MemFuse
Simple Chat App with Memory
This cookbook shows how to build a simple chat application with persistent memory using MemFuse's high-level API.
Setup
First, install the MemFuse package:
pip install memfuse fastapi uvicorn
Building the Chat App
from memfuse.llm import LLMClient
from memfuse import MemFuseConfig, Memory
import os
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel, Field
import uvicorn
import uuid
from datetime import datetime
app = FastAPI()
# Initialize MemFuse configuration
memfuse_config = MemFuseConfig(
memfuse_api_key=os.environ.get("MEMFUSE_API_KEY")
)
# Initialize the unified client
client = LLMClient(
memfuse_config=memfuse_config,
openai_api_key=os.environ.get("OPENAI_API_KEY")
)
# Initialize Memory client for user/profile management
memory_client = Memory(memfuse_config=memfuse_config)
# Define a default agent ID
DEFAULT_AGENT_ID = "chat-assistant"
class ChatRequest(BaseModel):
user_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
message: str
conversation_id: str = None
agent_id: str = DEFAULT_AGENT_ID
@app.post('/chat')
async def chat(request: ChatRequest):
try:
# Try to get or create user profile
profile = memory_client.get_profile(
user_id=request.user_id,
agent_id=request.agent_id
)
# If profile doesn't exist, create a basic one
if not profile:
memory_client.update_profile(
user_id=request.user_id,
agent_id=request.agent_id,
profile={"created_at": str(datetime.now())}
)
# Configure MemFuse with user-specific context
memfuse_config = MemFuseConfig(
memfuse_api_key=os.environ.get("MEMFUSE_API_KEY"),
user_id=request.user_id,
agent_id=request.agent_id,
conversation_id=request.conversation_id
)
client.update_config(memfuse_config)
# Call LLM through unified client
response = client.chat(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful AI assistant with consistent memory."},
{"role": "user", "content": request.message}
],
memory_options={
"max_memories": 10, # Include up to 10 relevant memories
"recency_bias": 0.3, # Weight recent memories slightly higher
}
)
return {
'response': response.content,
'conversation_id': response.conversation_id,
'user_id': request.user_id,
'agent_id': request.agent_id
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")
@app.post('/chat/stream')
async def chat_stream(request: ChatRequest):
try:
# Ensure user exists by checking/creating profile (same as in chat endpoint)
profile = memory_client.get_profile(
user_id=request.user_id,
agent_id=request.agent_id
)
if not profile:
memory_client.update_profile(
user_id=request.user_id,
agent_id=request.agent_id,
profile={"created_at": str(datetime.now())}
)
# Configure MemFuse with user-specific context
memfuse_config = MemFuseConfig(
memfuse_api_key=os.environ.get("MEMFUSE_API_KEY"),
user_id=request.user_id,
agent_id=request.agent_id,
conversation_id=request.conversation_id
)
client.update_config(memfuse_config)
async def generate():
# Stream through unified client
response_stream = client.chat(
model="gpt-4o",
messages=[
{"role": "user", "content": request.message}
],
stream=True
)
# Stream the response chunks
collected_content = ""
for chunk in response_stream:
if hasattr(chunk, 'content') and chunk.content:
content = chunk.content
collected_content += content
yield f"data: {content}\n\n"
# Send the conversation ID, user_id, and agent_id at the end
conversation_id = getattr(response_stream, 'conversation_id', None)
yield f"data: CONVERSATION_ID:{conversation_id}\n\n"
yield f"data: USER_ID:{request.user_id}\n\n"
yield f"data: AGENT_ID:{request.agent_id}\n\n"
return StreamingResponse(generate(), media_type='text/event-stream')
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing streaming request: {str(e)}")
class SearchRequest(BaseModel):
user_id: str
query: str
agent_id: str = DEFAULT_AGENT_ID
@app.post('/memories/search')
async def search_memories(request: SearchRequest):
try:
# Search for related memories
memories = memory_client.search_memory(
query=request.query,
user_id=request.user_id,
agent_id=request.agent_id,
limit=5
)
return {
'memories': [
{
'content': memory.content,
'timestamp': memory.timestamp,
'conversation_id': memory.conversation_id
} for memory in memories
],
'user_id': request.user_id,
'agent_id': request.agent_id
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error searching memories: {str(e)}")
if __name__ == '__main__':
uvicorn.run(app, host="0.0.0.0", port=8000)
Next Steps
This simple example shows how to build a memory-enabled chat app. To enhance it, you could:
- Add user authentication
- Create a frontend user interface
- Implement more advanced memory management features
- Add multi-agent interactions
- Try using different LLM providers