Skip to main content

LangChain memory with emotional intelligence by NeurobloomAI

Project description

๐Ÿง  PACT for LangChain

Drop-in memory replacement that makes your agents remember what matters.

PyPI version License: MIT Downloads


The Problem

Your LangChain agent forgets things. Important things.

# Standard LangChain memory
conversation.memory.save_context(
    {"input": "I'm really frustrated with this bug"}, 
    {"output": "I understand. Let's debug it."}
)

# 10 messages later...
conversation.memory.load_memory_variables({})
# Returns: Everything, including irrelevant details
# Missing: The emotional context that matters

Result: Your agent treats every message the same. No emotional awareness. No prioritization. Just a wall of text.


The Solution

PACT Memory tracks what matters - emotions, context, and relationships.

from pact_langchain import PACTMemory

memory = PACTMemory(api_key="your_key")
conversation = ConversationChain(llm=llm, memory=memory)

# Same interface, better memory
conversation.predict(input="I'm really frustrated with this bug")
# PACT tracks: emotional_state="frustrated", priority="high"

# 10 messages later...
memory.load_memory_variables({})
# Returns: Relevant context + emotional state + consolidated summary
# Your agent knows the user is frustrated and prioritizes accordingly

Installation

pip install pact-langchain

Requirements:

  • Python 3.8+
  • LangChain 0.1.0+
  • PACT API key (get one at neurobloom.ai)

Quick Start

Quick Start

pip install pact-langchain

from pact_langchain import PACTMemory

# Use with deployed API
memory = PACTMemory(
    api_key="your-key",
    api_url="https://pact-hx.onrender.com"  # Live API!
)

# Save conversation
memory.save_context(
    {"input": "Hello!"},
    {"output": "Hi there!"}
)

# Load context
context = memory.load_memory_variables({})

Basic Usage (Drop-in Replacement)

from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from pact_langchain import PACTMemory

# Replace this:
# from langchain.memory import ConversationBufferMemory
# memory = ConversationBufferMemory()

# With this:
memory = PACTMemory(api_key="sk_test_...")

# Everything else stays the same
llm = OpenAI(temperature=0.7)
conversation = ConversationChain(llm=llm, memory=memory)

conversation.predict(input="Hi, I'm working on a Python project")
conversation.predict(input="I'm stuck on async functions")
conversation.predict(input="This is really frustrating!")

# PACT automatically:
# โœ… Tracks emotional progression (calm โ†’ frustrated)
# โœ… Identifies key topics (Python, async, debugging)
# โœ… Consolidates old context to save tokens

With Emotional Context

memory = PACTMemory(
    api_key="sk_test_...",
    emotional_tracking=True,
    return_emotional_context=True
)

conversation = ConversationChain(llm=llm, memory=memory)

conversation.predict(input="I just got promoted!")
# Behind the scenes: emotional_state="excited", valence=0.8

# Access emotional state directly
state = memory.get_emotional_state()
print(state)
# {
#   "current_emotion": "excited",
#   "valence": 0.8,
#   "trend": "positive",
#   "key_emotions": ["joy", "pride"]
# }

With Context Consolidation

memory = PACTMemory(
    api_key="sk_test_...",
    context_consolidation=True,
    consolidation_threshold=10  # Consolidate after 10 messages
)

# After 10 messages, PACT automatically:
# 1. Summarizes old context
# 2. Keeps recent messages
# 3. Preserves emotional and topical highlights
# 4. Saves you tokens ๐Ÿ’ฐ

# Force consolidation manually
summary = memory.force_consolidation()
print(summary["consolidated_summary"])
# "User is debugging a Python async issue, feeling frustrated but making progress..."

Side-by-Side Comparison

Standard LangChain Memory

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.save_context(
    {"input": "I'm excited about this project!"}, 
    {"output": "That's great!"}
)
memory.save_context(
    {"input": "Actually, I'm really stressed now."}, 
    {"output": "I can help with that."}
)

# Load memory
context = memory.load_memory_variables({})
print(context["history"])
# Human: I'm excited about this project!
# AI: That's great!
# Human: Actually, I'm really stressed now.
# AI: I can help with that.

# โŒ No emotional tracking
# โŒ No context prioritization
# โŒ No consolidation
# โŒ Grows unbounded (token explosion)

PACT Memory

from pact_langchain import PACTMemory

memory = PACTMemory(api_key="sk_test_...")
memory.save_context(
    {"input": "I'm excited about this project!"}, 
    {"output": "That's great!"}
)
memory.save_context(
    {"input": "Actually, I'm really stressed now."}, 
    {"output": "I can help with that."}
)

# Load memory
context = memory.load_memory_variables({})
print(context["history"])
# [Same conversation history]

print(context["emotional_state"])
# "stressed" (tracks emotional shift)

print(context["context_summary"])
# "User's emotional state shifted from excited to stressed regarding project"

# โœ… Emotional tracking
# โœ… Context prioritization
# โœ… Automatic consolidation
# โœ… Token-efficient

Features

Feature Standard LangChain PACT Memory
Drop-in replacement โœ… โœ…
Emotional tracking โŒ โœ…
Context consolidation โŒ โœ…
Priority management โŒ โœ…
Token optimization โŒ โœ…
Relationship patterns โŒ โœ…
Memory visualization โŒ โœ…
Async support โœ… โœ…

Advanced Usage

Custom Configuration

memory = PACTMemory(
    api_key="sk_test_...",
    
    # Emotional tracking
    emotional_tracking=True,
    return_emotional_context=True,
    
    # Context management
    context_consolidation=True,
    consolidation_threshold=15,  # Consolidate after N messages
    max_token_limit=2000,        # Max tokens in context
    
    # API settings
    api_url="https://api.neurobloom.ai/pact/v1"  # Custom endpoint
)

Accessing Memory Graph

# Get full memory graph structure
graph = memory.get_context_graph()

# Structure:
# {
#   "nodes": [
#     {"id": "msg_1", "type": "message", "content": "...", "emotion": "excited"},
#     {"id": "topic_python", "type": "topic", "importance": 0.9}
#   ],
#   "edges": [
#     {"from": "msg_1", "to": "topic_python", "type": "mentions"}
#   ]
# }

# Use this for visualization in your own UI

Manual Priority Control

# Mark important topics
memory.set_context_priority(topic="quarterly_goals", priority="high")
memory.set_context_priority(topic="lunch_preferences", priority="low")

# PACT will:
# - Keep high-priority context longer
# - Consolidate low-priority context sooner
# - Retrieve high-priority context first

Async Support

from pact_langchain import AsyncPACTMemory

memory = AsyncPACTMemory(api_key="sk_test_...")

# Use with async chains
async def chat():
    context = await memory.aload_memory_variables({})
    await memory.asave_context(
        {"input": "Hello"}, 
        {"output": "Hi there!"}
    )

Real-World Example: Customer Support Bot

from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from pact_langchain import PACTMemory

# Initialize with emotional tracking
memory = PACTMemory(
    api_key="sk_prod_...",
    emotional_tracking=True,
    context_consolidation=True,
    consolidation_threshold=20
)

llm = OpenAI(temperature=0.7)
support_bot = ConversationChain(
    llm=llm, 
    memory=memory,
    verbose=True
)

# Customer conversation
support_bot.predict(input="My order hasn't arrived")
# PACT detects: emotion="concerned"

support_bot.predict(input="It's been 3 weeks!")
# PACT detects: emotion="frustrated", escalation=True

support_bot.predict(input="This is unacceptable!")
# PACT detects: emotion="angry", priority="high"

# Check emotional state
state = memory.get_emotional_state()
if state["current_emotion"] == "angry":
    # Escalate to human agent
    print("โš ๏ธ  Customer is angry - escalating to human agent")
    
# Get context summary for human agent
context = memory.load_memory_variables({})
print(context["context_summary"])
# "Customer ordered 3 weeks ago, item not delivered. 
#  Emotional progression: concerned โ†’ frustrated โ†’ angry"

Comparison with Alternatives

vs. ConversationBufferMemory

  • โœ… PACT tracks emotions, buffer doesn't
  • โœ… PACT consolidates context, buffer grows unbounded
  • โœ… PACT prioritizes, buffer treats everything equal

vs. ConversationSummaryMemory

  • โœ… PACT preserves emotional nuance, summary loses it
  • โœ… PACT uses smart consolidation, summary is aggressive
  • โœ… PACT provides graph structure, summary is just text

vs. ConversationKGMemory (Knowledge Graph)

  • โœ… PACT includes emotional edges, KG doesn't
  • โœ… PACT has built-in consolidation, KG doesn't
  • โœ… PACT is a managed service, KG requires manual setup

Pricing

Plan Price Storage Features
Free $0 10K tokens/month Basic memory, public data
Starter $20/mo 100K tokens Emotional tracking
Pro $99/mo 1M tokens Full features, analytics
Team $299/mo Unlimited Shared context, priority support

All plans include:

  • Unlimited API calls
  • Context consolidation
  • 99.9% uptime SLA
  • SOC 2 compliance

View detailed pricing โ†’


Examples

Basic Chatbot

# examples/basic_usage.py
from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from pact_langchain import PACTMemory

memory = PACTMemory(api_key="sk_test_...")
llm = OpenAI(temperature=0.7)
conversation = ConversationChain(llm=llm, memory=memory)

while True:
    user_input = input("You: ")
    if user_input.lower() == "quit":
        break
    
    response = conversation.predict(input=user_input)
    print(f"Bot: {response}")
    
    # Show emotional state
    state = memory.get_emotional_state()
    print(f"[Emotion: {state['current_emotion']}]")

Therapy/Coaching Bot

See examples/emotional_tracking_complete.py

Customer Support Agent

See examples/support_agent.py


Documentation


How It Works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Your LangChain โ”‚
โ”‚      Agent      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ”‚ save_context() / load_memory_variables()
         โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  PACT Memory    โ”‚  โ† Drop-in replacement
โ”‚  (This Package) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ”‚ API calls (REST)
         โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   PACT Server   โ”‚  โ† Managed service by NeurobloomAI
โ”‚                 โ”‚  โ† Handles emotional analysis
โ”‚                 โ”‚  โ† Context consolidation
โ”‚                 โ”‚  โ† Graph storage
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Under the hood:

  1. Your agent calls memory.save_context() like normal
  2. PACT extracts emotional signals from the text
  3. PACT builds a context graph (topics, relationships, emotions)
  4. PACT consolidates old context when threshold is hit
  5. Your agent calls memory.load_memory_variables()
  6. PACT returns optimized context + emotional metadata

FAQ

Q: Does this work with existing LangChain code?

A: Yes! It's a drop-in replacement for ConversationBufferMemory. Just change the import.

Q: Do I need to change my prompts?

A: No. The emotional context is added as separate variables. Your prompts work as-is, but you can optionally reference {emotional_state} if you want.

Q: How much does it cost?

A: Free tier: 10K tokens/month. Paid plans start at $20/month. See pricing โ†’

Q: Where is my data stored?

A: On PACT's secure servers (SOC 2 compliant). You can also self-host the PACT server.

Q: Can I use this offline?

A: Not yet, but self-hosted version is coming in Q2 2026.

Q: Does it work with LangChain agents?

A: Yes! Works with chains, agents, and any LangChain component that uses memory.

Q: What about privacy?

A: All data is encrypted in transit and at rest. You can delete sessions anytime. See Privacy Policy.

Q: Can I visualize the memory graph?

A: Yes! Use memory.get_context_graph() to export, or use PACT Studio for a visual UI.


Roadmap

  • Core memory integration
  • Emotional tracking
  • Context consolidation
  • Async support
  • Self-hosted option (Q2 2026)
  • Multi-session support (Q2 2026)
  • LangSmith integration (Q3 2026)
  • Voice tone analysis (Q3 2026)

View full roadmap โ†’


Contributing

We welcome contributions! See CONTRIBUTING.md

Quick start:

git clone https://github.com/neurobloomai/pact-hx.git
cd pact-hx/packages/langchain
pip install -e ".[dev]"
pytest

Support


License

MIT License - see LICENSE


Acknowledgments

Built with โค๏ธ for the LangChain community by NeurobloomAI.

Special thanks to:

  • LangChain team for the amazing framework
  • Early beta testers who provided feedback
  • Contributors who made this possible

Star History

If you find this useful, give us a star! โญ

Star History Chart


Made with ๐Ÿง  by NeurobloomAI

Website โ€ข Docs โ€ข Discord โ€ข Twitter

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pact_langchain-0.1.0.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pact_langchain-0.1.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file pact_langchain-0.1.0.tar.gz.

File metadata

  • Download URL: pact_langchain-0.1.0.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.13

File hashes

Hashes for pact_langchain-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dedb4b76b7919c3cce1739617846623335bfe5f6669409ca23cfe9c01939f7ad
MD5 b1c5faa1cfeace7feb26d9fcc65c2677
BLAKE2b-256 5666031bb9c285f553c4aea4795da6ff49cb5482b39127b6583ec725700ab7bf

See more details on using hashes here.

File details

Details for the file pact_langchain-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pact_langchain-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.13

File hashes

Hashes for pact_langchain-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fcc73b19568d32600bdf7d1b593932c67f2c42090e75f4b13df1176ade8791fd
MD5 0ac0ac1fa3292d1f08da131b609b3aa0
BLAKE2b-256 ef2a56a6bc8120473cd960996b4427af1b2fb5733eb07e3e83e0548c13ff58dc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page