Skip to main content
If you came from the LangChain recipe, this page gives the longer comparison. LangChain memory classes live inside your process. They keep buffers, summaries, or graphs near the chain. Tex stores memory outside the process and returns the relevant slice when you call recall.

Mapping

LangChainTex equivalent
ConversationBufferMemoryrecall(q=user_msg, session_id=sid, top_k=20) returns the relevant 20 turns instead of the last N.
ConversationBufferWindowMemory(k=10)recall(q=user_msg, session_id=sid, top_k=10) uses the same k, but ranks by relevance.
ConversationSummaryMemoryTex stores extracted observations automatically. Read them from recall’s hits.observations.
ConversationKGMemoryTex builds an entity graph in the background. Query via hits.entities (linked across observations).

Migration

from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferWindowMemory
from langchain_openai import ChatOpenAI

memory = ConversationBufferWindowMemory(k=10, return_messages=True)
chain = ConversationChain(
    llm=ChatOpenAI(model="gpt-4o"),
    memory=memory,
)

answer = chain.invoke({"input": user_msg})["response"]

Trade-offs

LangChain memory has no network hop. Tex adds a network call: writes are usually around 150ms, and reads can take a few seconds. In return, memory survives deploys, prompts stay bounded, sessions can share memory, and each recall has a confidence score. For a small hobby bot, a buffer may be enough. For a customer-facing app, Tex is usually the cleaner path.

Drop-in adapter (optional)

If your codebase has dozens of LangChain chains and you’d rather not rewrite them all, wrap Tex in a BaseChatMemory subclass:
tex_chat_memory.py
from typing import Any
from langchain.memory.chat_memory import BaseChatMemory
from langchain.schema import BaseMessage, HumanMessage, AIMessage
from tex import Tex

class TexChatMemory(BaseChatMemory):
    def __init__(self, tex: Tex, session_id: str, top_k: int = 10, **kw):
        super().__init__(**kw)
        self._tex = tex
        self._session_id = session_id
        self._top_k = top_k

    @property
    def memory_variables(self) -> list[str]:
        return ["history"]

    def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, Any]:
        q = inputs.get("input", "")
        hits = self._tex.recall(q=q, session_id=self._session_id, top_k=self._top_k)
        history = "\n".join(f"- {h.text}" for h in hits.hits.turns)
        return {"history": history}

    def save_context(self, inputs: dict[str, Any], outputs: dict[str, Any]) -> None:
        self._tex.conversations.remember(
            session_id=self._session_id,
            turns=[
                {"role":"user","text": inputs["input"], "timestamp": now_iso()},
                {"role":"assistant","text": outputs["response"], "timestamp": now_iso()},
            ],
        )

    def clear(self) -> None:
        # No-op. Tex memory persists by design.
        pass
Use it like any other LangChain memory:
chain = ConversationChain(
    llm=ChatOpenAI(),
    memory=TexChatMemory(tex=tex, session_id="chat-1"),
)