Chat Memory with OpenAI Integration
This tutorial demonstrates how to build a chat application that stores conversation history using Papr's Messages API and uses it to enhance OpenAI responses.
Updated for Messages API: This tutorial uses the new Messages API (
/v1/messages), which is specifically designed for chat applications with built-in session management and automatic memory creation.
Production-Ready Reference Implementation
If you're looking for a complete, production-ready implementation of a chat application with memory capabilities, check out our open-source PaprChat project. PaprChat is built on Next.js 14 and demonstrates all the concepts covered in this tutorial in a full-featured application.
Key features of PaprChat:
- Long-term memory for personalized chat experiences powered by Papr
- Automatic storage and retrieval of relevant conversations
- RAG (Retrieval-Augmented Generation) capabilities
- Semantic search across conversation history
- Persistent memory storage in the cloud
- Built with Next.js 14 App Router
- AI SDK for unified LLM interactions
- Beautiful UI with shadcn/ui and Tailwind CSS
- Component primitives from Radix UI
- Production-ready with Neon Serverless Postgres, Vercel Blob storage, and Auth.js
Model Support: PaprChat ships with xAI grok-2-1212 as the default chat model, but supports multiple providers through the AI SDK including OpenAI, Anthropic, Cohere, and many more.
Deployment: You can deploy your own instance of PaprChat with one click using the deploy button in the repository. The deployment process will set up:
- Your GitHub repository clone
- A new Vercel project
- Neon PostgreSQL database provisioning
- Vercel Blob Storage configuration
- Required environment variables setup
For detailed setup instructions and customization options, visit our deployment guide.
Prerequisites
Before you begin, you'll need:
- A Papr Memory API key
- An OpenAI API key
- Node.js installed
Implementation
1. Project Setup
Create a new project and install dependencies:
mkdir chat-memory
cd chat-memory
npm init -y
npm install express dotenv node-fetch openai
npm install @papr/memoryCreate a .env file:
PAPR_MEMORY_API_KEY=your_papr_api_key_here
OPENAI_API_KEY=your_openai_api_key_here2. Creating the Chat Application
Create app.js:
import { OpenAI } from 'openai';
import Papr from '@papr/memory';
import express from 'express';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
app.use(express.json());
// Initialize OpenAI and Papr client
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
const paprClient = new Papr({
apiKey: process.env.PAPR_MEMORY_API_KEY
});
// Store chat message using Messages API
async function storeMessage(message, role, sessionId) {
try {
const response = await paprClient.messages.store({
content: message,
role: role,
session_id: sessionId,
external_user_id: "user_123",
process_messages: true // Automatically create memories from important messages
});
return response;
} catch (error) {
throw new Error(`Failed to store message: ${error.message}`);
}
}
// Get recent conversation history
async function getConversationHistory(sessionId, limit = 20) {
try {
const history = await paprClient.messages.getHistory({
session_id: sessionId,
limit: limit
});
return history;
} catch (error) {
throw new Error(`Failed to get conversation history: ${error.message}`);
}
}
// Get compressed context for longer conversations
async function getCompressedContext(sessionId) {
try {
const compressed = await paprClient.messages.compressSession({
session_id: sessionId
});
return compressed.context_for_llm;
} catch (error) {
// If compression fails (e.g., too few messages), return null
return null;
}
}
// Process a chat message
app.post('/chat', async (req, res) => {
try {
const { message, sessionId } = req.body;
if (!message || !sessionId) {
return res.status(400).json({ error: 'Missing required fields' });
}
// Store user message
await storeMessage(message, 'user', sessionId);
// Get conversation history
const history = await getConversationHistory(sessionId);
// Build context from conversation history
let context = "";
// For conversations with 20+ messages, use compressed context
if (history.total_count >= 20) {
const compressed = await getCompressedContext(sessionId);
if (compressed) {
context = compressed;
}
}
// For shorter conversations, use recent messages
if (!context && history.messages) {
context = history.messages
.map(msg => `${msg.role}: ${msg.content}`)
.join('\n');
}
// Create messages for OpenAI
const messages = [
{ role: "system", content: "You are a helpful assistant. Use the conversation history provided to give contextual responses." }
];
if (context) {
messages.push({
role: "system",
content: `Here is the conversation history:\n${context}`
});
}
messages.push({ role: "user", content: message });
// Get response from OpenAI
const completion = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: messages,
});
const aiResponse = completion.choices[0].message.content;
// Store assistant response
await storeMessage(aiResponse, 'assistant', sessionId);
// Send response to client
res.json({
message: aiResponse,
sessionId
});
} catch (error) {
console.error('Error processing chat:', error);
res.status(500).json({ error: error.message });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});3. Update package.json
Update your package.json to include:
{
"name": "chat-memory",
"version": "1.0.0",
"description": "Chat app with Papr Memory and OpenAI",
"main": "app.js",
"type": "module",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"@papr/memory": "^1.0.0",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"openai": "^4.0.0"
}
}Usage
- Start the server:
npm start- Send a message:
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{
"message": "What are the benefits of using a vector database?",
"sessionId": "session_123"
}'- Continue the conversation with follow-up questions:
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{
"message": "How does that compare to traditional databases?",
"sessionId": "session_123"
}'How It Works
User Message Flow:
- User sends a message
- Message is stored using Messages API with
process_messages: true - App retrieves conversation history
- For 20+ messages, compression is used automatically
- OpenAI receives the user message + context from history
- OpenAI generates a response
- Response is stored using Messages API
- Response is sent back to the user
Messages API Integration:
- Each message is stored with role, session ID, and external user ID
- Messages API automatically creates memories from important messages
- Built-in session management and compression
- No need for manual metadata tagging
Automatic Compression:
- For conversations with 20+ messages, context is compressed
- Compression provides hierarchical summaries (short/medium/long-term)
- Reduces token usage in OpenAI calls
- Maintains conversation quality with intelligent summarization
Benefits:
- Automatic Memory Creation: Important messages become searchable memories
- Built-in Compression: Long conversations don't consume excessive tokens
- Session Management: Messages grouped by session automatically
- Context Awareness: OpenAI has access to full conversation context
- Scalable: Works efficiently for short and long conversations
Comparing with PaprChat
While this tutorial provides a simple implementation to understand the core concepts, PaprChat offers a more sophisticated approach:
| Feature | This Tutorial | PaprChat |
|---|---|---|
| UI | None (API only) | Modern Next.js UI with shadcn/ui and Radix UI |
| Authentication | None | Auth.js integration |
| Database | None | Neon Serverless Postgres |
| File Handling | None | Vercel Blob Storage |
| AI Providers | OpenAI only | Multiple providers (xAI, OpenAI, Anthropic, Cohere) |
| Memory | Basic implementation | Advanced with RAG capabilities |
| Deployment | Manual | One-click Vercel deployment |
| Storage | In-memory | Persistent cloud storage |
| Graph Support | Limited | Full agentic graph capabilities |
Next Steps
- Deploy PaprChat with one click for a complete solution
- Customize the chat interface in the
components/directory - Configure your preferred AI provider settings in
config/ai.ts - Explore the API references in our developer documentation
- Join our Discord community for support and discussions