GEPA adapter for LangChain v1 — optimize prompts for chat models, agents, and LangGraph pipelines
Project description
langchain-gepa-adapter
GEPA adapter for LangChain v1. Optimize the prompts (and other text components) of any LangChain pipeline — a single chat model, an agent built with langchain.agents.create_agent, a custom LangGraph graph, RAG, etc. — using the GEPA reflective evolutionary optimizer.
Install
pip install langchain-gepa-adapter
# or, from a clone:
uv sync # core only
uv sync --extra examples # adds datasets, dotenv, etc. for the example scripts
Quickstart
Two things are required
rollout_fn(candidate, example) -> state— create a langgraph state, runs the candidate prompt with the example and returns the generates a final state objecteval_fn(example, state) -> (score, feedback)— scores the rollout. The feedback string is what GEPA's reflection LM reads when proposing improvements
from gepa import optimize
from langchain.chat_models import init_chat_model
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_gepa_adapter import (
LangChainGEPAAdapter,
last_message_text,
make_default_proposer,
make_reflection_lm,
)
task_llm = init_chat_model("openai:gpt-4o-mini")
reflection_llm = init_chat_model("openai:gpt-5-mini")
def rollout(candidate, example):
messages = [
SystemMessage(candidate["system_prompt"]),
HumanMessage(example["input"]),
]
result = task_llm.invoke(messages)
if not isinstance(result, AIMessage):
result = AIMessage(content=str(result.content))
return {"messages": messages + [result]}
def evaluate(example, state):
response = last_message_text(state)
if example["answer"] in response:
return 1.0, "Correct."
return 0.0, f"Wrong. Expected {example['answer']}."
reflection = make_reflection_lm(reflection_llm)
adapter = LangChainGEPAAdapter(
rollout_fn=rollout,
eval_fn=evaluate,
custom_proposer=make_default_proposer(reflection),
)
result = optimize(
seed_candidate={"system_prompt": "Answer the question."},
trainset=train_set,
valset=val_set,
adapter=adapter,
reflection_lm=reflection,
max_metric_calls=500,
)
print(result.best_candidate["system_prompt"])
Agents and tools
rollout_fn returns a state dict, so any LangGraph state — including agents built with create_agent — is supported directly:
from langchain.agents import create_agent
from langchain_core.tools import tool
@tool
def calculator(a: int, b: int, op: str) -> str:
...
def rollout(candidate, example):
agent = create_agent(
model=task_llm,
tools=[calculator],
system_prompt=candidate["system_prompt"],
)
return agent.invoke({"messages": [HumanMessage(example["input"])]})
evaluate can then walk state["messages"] to inspect tool calls, not just the final response.
Prompt Optimization Examples
| Script | Task | command |
|---|---|---|
examples/pair_sum_product.py |
Single Turn LLM prompt optimization with a synthetic problem | uv run python examples/pair_sum_product.py |
examples/big_number_arithmetic.py |
Multi-digit arithmetic with a calculator tool-using agent. Uses create_agent |
uv run python examples/big_number_arithmetic.py |
examples/aime.py |
AIME competition math from HuggingFace datasets |
uv run python examples/aime.py |
examples/gsm8k.py |
GSM8K grade-school word problems from HuggingFace datasets |
uv run python examples/gsm8k.py |
uv run python examples/big_number_arithmetic.py
# Private LLM params via JSON
uv run python examples/big_number_arithmetic.py \
--task-model-config llm_configs/gpt-5-mini.json \
--reflection-model-config llm_configs/gpt-5.json
Model configs
The example scripts default to standard LangChain model strings (openai:gpt-4o-mini, etc.). For custom LLMs, write your init_chat_model kwargs to a JSON file and pass --task-model-config <path>:
{
"model": "gpt-5-mini",
"model_provider": "openai",
"base_url": "https://your-gateway.example.com/openai/gpt-5-mini",
"api_key": "...",
"default_headers": {"custom-header-key": "xyz"}
}
load_chat_model("openai:gpt-5-mini", config_path="path.json") loads the JSON when given, otherwise falls back to the model string. Keep the JSON files outside source control — llm_configs/ is already gitignored.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file langchain_gepa_adapter-0.1.0.tar.gz.
File metadata
- Download URL: langchain_gepa_adapter-0.1.0.tar.gz
- Upload date:
- Size: 15.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
412082128151a3a47d16f7dc26a0d6b2c137b9d0720004dbae399f7ed89b3d8a
|
|
| MD5 |
e733b6a31bf2674fca702af572e831d2
|
|
| BLAKE2b-256 |
89671df1abf3e176157946964e2cd66b89221a802a2f239fd326563535fbc221
|
Provenance
The following attestation bundles were made for langchain_gepa_adapter-0.1.0.tar.gz:
Publisher:
release.yml on bryonkucharski/langchain-gepa-adapter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_gepa_adapter-0.1.0.tar.gz -
Subject digest:
412082128151a3a47d16f7dc26a0d6b2c137b9d0720004dbae399f7ed89b3d8a - Sigstore transparency entry: 1574134799
- Sigstore integration time:
-
Permalink:
bryonkucharski/langchain-gepa-adapter@8776f12c797486642167c31e3c37976d27b510c4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bryonkucharski
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8776f12c797486642167c31e3c37976d27b510c4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file langchain_gepa_adapter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: langchain_gepa_adapter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f04450629284fe98067360992f929aac0b7f64a1449a94cab89858416b16754
|
|
| MD5 |
a22512aebe4f91d97768a232502d7a82
|
|
| BLAKE2b-256 |
4fa39b1e41828077f433f19176f7a3b8b4375878c2731a7dccf67c885773502b
|
Provenance
The following attestation bundles were made for langchain_gepa_adapter-0.1.0-py3-none-any.whl:
Publisher:
release.yml on bryonkucharski/langchain-gepa-adapter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_gepa_adapter-0.1.0-py3-none-any.whl -
Subject digest:
9f04450629284fe98067360992f929aac0b7f64a1449a94cab89858416b16754 - Sigstore transparency entry: 1574134803
- Sigstore integration time:
-
Permalink:
bryonkucharski/langchain-gepa-adapter@8776f12c797486642167c31e3c37976d27b510c4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bryonkucharski
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8776f12c797486642167c31e3c37976d27b510c4 -
Trigger Event:
push
-
Statement type: