Skip to content

Chapter 8 of 8

Observability, Evaluation, Deployment, and Caching

LangChain's observability story centers on callbacks and LangSmith. A BaseCallbackHandler subclass implements lifecycle hooks — on_llm_start, on_chat_model_start, on_llm_new_token, on_llm_end, and on_llm_error for model runs; on_chain_start and on_chain_end for any runnable; on_tool_start and on_tool_end for tools. Nested runnables emit nested start and end pairs correlated by run_id and parent_run_id, so you can trace a single invoke call all the way down. Handlers are passed via config per call or attached globally. LangSmith is the hosted platform that consumes these callbacks: setting the LANGSMITH_TRACING flag and the API key automatically logs every LangChain run, and the result is a hierarchical Run Tree you can browse, replay, and compare on smith.langchain.com. The free tier includes limited traces per month; paid plans add longer retention, datasets, evaluators, and team collaboration features.

Evaluation reuses the same primitives. LangChain's evaluation module defines a StringEvaluator interface — subclasses implement _evaluate_strings and return a dict with a score and optional reasoning. Concrete examples include exact-match and regex-match evaluators, embedding-distance metrics such as cosine, euclidean, and Manhattan, and LLM-judged evaluators like CriteriaEvalChain (does the prediction satisfy a custom criterion?) and PairwiseStringEvaluator (compare two outputs head-to-head, returning A, B, or tie). You create a dataset with the LangSmith Client (a list of input and reference pairs) and run an evaluation with a target chain, a dataset, and an evaluator to score your chain. Writing a custom evaluator is straightforward: subclass StringEvaluator, set requires_input, requires_reference, and evaluation_name, and implement _evaluate_strings. To control LLM cost in production, combine with_retry for transient errors with a callback that records token usage and a guard runnable that short-circuits when a per-user or daily budget is exceeded.

Deployment and caching round out the picture. LangServe takes any Runnable and exposes it as a REST API with FastAPI; add_routes automatically creates invoke, batch, stream, stream_log, and playground endpoints, generates an input and output JSON schema, and accepts a RunnableConfig factory for runtime overrides. The caching layer avoids redundant LLM calls: set_llm_cache accepts InMemoryCache for tests, SQLiteCache or RedisCache for local persistence, and RedisSemanticCache for similarity-based caching where two semantically equivalent prompts return the same stored response (configured with a score_threshold). Caches are keyed by the serialized prompt plus model parameters. LangChain Templates, the older gallery of pre-built project templates, has been archived in favor of the langgraph new CLI for new projects. Together, callbacks, LangSmith, LangServe, and caching give you the operational scaffolding to take a prototype into production with traceability, evaluation, and cost controls.

All chapters
  1. 1Foundations of LangChain and the Runnable Interface
  2. 2Prompts, Chat Models, and Output Parsers
  3. 3Composing Runnables and Controlling Execution
  4. 4Memory and Conversation History
  5. 5Documents, Embeddings, and Vector Stores
  6. 6RAG Pipelines and Document Processing
  7. 7Tools, Agents, and LangGraph
  8. 8Observability, Evaluation, Deployment, and Caching

Drill it

Reading is not remembering. These come from the LangChain deck:

Q

What is LangChain?

LangChain is an open-source Python framework for building applications powered by large language models (LLMs). It provides modular components for prompts, chai...

Q

What is LCEL (LangChain Expression Language)?

LCEL is a declarative syntax for composing LangChain components using the pipe operator (|). It creates RunnableSequence chains that support streaming, batching...

Q

How do you create a ChatPromptTemplate?

Use ChatPromptTemplate.from_messages() with a list of (role, template) tuples. Variables are wrapped in curly braces.from langchain_core.prompts import ChatProm...

Q

How do you invoke a ChatModel in LangChain?

Instantiate the model class and call .invoke() with a list of messages or a prompt value. The model returns an AIMessage.from langchain_openai import ChatOpenAI...