ProvenPin Install

LangChain (Python) LCEL chain with structured parsing, tested with a fake chat model: working versions (tested 2026-10-15)

Compose ChatPromptTemplate, a chat model and a Pydantic output parser with LCEL in langchain-core, tested offline using GenericFakeChatModel.

passed5 passed · 0 failed2026-10-15 13:31 UTC
Status
passed
Last passed
2026-10-15 13:31 UTC
Tests
5 / 5
Language
Python
Runtime
Python 3.13.16
pinned versions3
langchain-core@1.6.10pydantic@2.14.1pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38742087302

The code

Exactly the files that passed. Your agent can pull them with get_recipe("langchain-core-fake-llm-python") (install), or see them on GitHub.

requirements.txt
langchain-core==1.6.10
pydantic==2.14.1
pytest==9.1.1
chain.py
from langchain_core.language_models import BaseChatModel
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

class Sentiment(BaseModel):
    label: str = Field(pattern="^(positive|negative|neutral)$")
    score: float = Field(ge=0, le=1)

parser = PydanticOutputParser(pydantic_object=Sentiment)
prompt = ChatPromptTemplate.from_messages([
    ("system", "Classify sentiment.\n{format_instructions}"),
    ("human", "{text}"),
]).partial(format_instructions=parser.get_format_instructions())

def build_chain(model: BaseChatModel):
    return prompt | model | parser
tests/test_chain.py
import pytest
from langchain_core.exceptions import OutputParserException
from langchain_core.language_models.fake_chat_models import GenericFakeChatModel
from langchain_core.messages import AIMessage
from chain import Sentiment, build_chain, prompt

def fake(*replies):
    return GenericFakeChatModel(messages=iter([AIMessage(content=r) for r in replies]))

def test_parses_structured_output():
    out = build_chain(fake('{"label": "positive", "score": 0.9}')).invoke({"text": "love it"})
    assert out == Sentiment(label="positive", score=0.9)

def test_parses_fenced_json():
    out = build_chain(fake('```json\n{"label": "neutral", "score": 0.5}\n```')).invoke({"text": "ok"})
    assert out.label == "neutral"

def test_bad_output_raises():
    with pytest.raises(OutputParserException):
        build_chain(fake('{"label": "angry", "score": 3}')).invoke({"text": "grr"})

def test_prompt_includes_format_instructions():
    msgs = prompt.format_messages(text="hi")
    assert "score" in msgs[0].content and msgs[1].content == "hi"

def test_batch():
    outs = build_chain(fake('{"label":"positive","score":1}', '{"label":"negative","score":0.1}')).batch([{"text": "a"}, {"text": "b"}], config={"max_concurrency": 1})
    assert [o.label for o in outs] == ["positive", "negative"]
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.