feat(instrument): LangChain LCEL support (RunnableSequence/Parallel/Lambda/Passthrough/Branch)#131
Closed
mmercuri wants to merge 1 commit into
Conversation
…ugh/Branch) Adds LangChain Expression Language (LCEL) tracing to the LangChain adapter, fixing spec 04b §1 weakness #4: LCEL is the dominant authoring pattern in langchain-core 0.2+, but the adapter's chain handlers were written for the legacy Chain API and treated LCEL pipelines as opaque unless a langgraph_node marker was present. What is added ------------- - src/layerlens/instrument/adapters/frameworks/langchain/lcel.py - RunnableKind enum (sequence/parallel/lambda/passthrough/branch/other) - detect_runnable_kind() — classify from the on_chain_start `name` kwarg - parse_composition_tag() — decode seq:step:N / map:key:K / branch:N / condition:N tags into a CompositionPosition - parse_parallel_branches() — extract branch keys from "RunnableParallel<a,b>" name strings - fingerprint_lambda() — deterministic SHA-256 over (name, depth, position) for diff-friendly lambda identity - LCELRunnableTracker — per-handler state machine that records the active runnable hierarchy across nested invocations and produces composition payloads at root completion - src/layerlens/instrument/adapters/frameworks/langchain/callbacks.py - on_chain_start/end/error wired through the tracker; LangGraph node behavior pre-empts LCEL tracking to avoid double-emission - Per-runnable agent.input (L1), agent.output (L1), agent.code (L2) events with composition metadata - Synthetic chain.composition snapshot emitted as an agent.code event with `kind="chain.composition"` at root completion (success or error) so debuggers see the full executed graph in one record - Tracker reset on disconnect() - tests/instrument/adapters/frameworks/langchain/test_lcel.py - 43 tests covering all five Runnable types, tag parsing, hierarchy construction, composition payload, error paths, capture-config gating, LangGraph non-regression, RunnableConfig propagation, and fingerprint determinism - samples/instrument/langchain/lcel_main.py - Runnable LCEL pipeline (RAG-style: parallel | lambda | lambda | branch) demonstrating all five primitives; runs offline with deterministic stand-ins, no API key required - docs/adapters/frameworks-langchain-lcel.md - Coverage matrix for all five primitives + RunnableConfig - Event reference (agent.input / agent.output / agent.code + composition snapshot schema) - Capture-config gating, hierarchy/depth semantics, lambda fingerprinting, and LangGraph interaction notes Validation ---------- - uv run pytest tests/instrument/adapters/frameworks/langchain/ -x -> 43 passed - uv run pytest tests/instrument/adapters/frameworks/ (full subtree) -> 80 passed (43 new LCEL + 37 baseline; no regression) - uv run mypy --strict src/layerlens/instrument/adapters/frameworks/langchain/ -> Success: no issues found in 7 source files - uv run ruff check src/.../langchain/ tests/.../langchain/ -> All checks passed - uv run pyright src/.../langchain/ -> 0 errors, 0 warnings, 0 informations - python -m samples.instrument.langchain.lcel_main -> exit 0, 28 events captured (9 agent.input, 9 agent.code, 1 chain.composition snapshot, 9 agent.output) Spec reference: docs/incubation-docs/adapter-framework/04-per-framework-specs/04b-langchain-adapter-spec.md §1 weakness #4 and §4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds first-class LangChain Expression Language (LCEL) tracing to the LangChain adapter, fixing spec 04b §1 weakness #4. LCEL is the dominant authoring pattern as of
langchain-core 0.2+(theprompt | llm | parserpipe pattern), and the adapter previously treated LCEL pipelines as opaque unless alanggraph_nodemarker was present.The adapter now:
on_chain_startcallbacks:RunnableSequence,RunnableParallel<a,b,...>,RunnableLambda,RunnablePassthrough,RunnableBranchseq:step:N,map:key:K,branch:N,condition:N) so children know where they sit in the parentagent.input/agent.output) and L2 (agent.code) with kind, depth, position, parallel-branch keys, passthrough markers, and SHA-256 lambda fingerprintschain.compositionsnapshot as anagent.codeevent at root completion (success or error) so the dashboard can render the full executed DAG without reconstructing it from the per-step streammetadata["langgraph_node"]is present, the existing LangGraph attribution path runs and LCEL tracking is suppressed for that subtree (no double-emission)tagsandmetadataflow through the callback chain; user-supplied tags don't confuse position parsingFiles
src/layerlens/instrument/adapters/frameworks/langchain/lcel.py(new, 365 lines) —RunnableKind,LCELRunnableTracker,CompositionPosition,LCELNode, helper functionssrc/layerlens/instrument/adapters/frameworks/langchain/callbacks.py(modified) —on_chain_start/end/errorwired through the trackersrc/layerlens/instrument/adapters/frameworks/langchain/__init__.py— public LCEL surfacetests/instrument/adapters/frameworks/langchain/test_lcel.py(new, 43 tests)samples/instrument/langchain/lcel_main.py(new) — runs offline, no API keydocs/adapters/frameworks-langchain-lcel.md(new) — coverage matrix + event referenceTest plan
uv run pytest tests/instrument/adapters/frameworks/langchain/test_lcel.py -x— 43/43 passeduv run pytest tests/instrument/adapters/frameworks/— 80/80 passed (43 new + 37 baseline; no regression in the autogen/crewai/langfuse adapters)uv run mypy --strict src/layerlens/instrument/adapters/frameworks/langchain/— Success: no issues found in 7 source filesuv run ruff check src/.../langchain/ tests/.../langchain/— All checks passeduv run pyright src/.../langchain/— 0 errors, 0 warnings, 0 informationspython -m samples.instrument.langchain.lcel_main— exit 0, captures 28 events (9agent.input, 9agent.codeper-step, 1chain.compositionsnapshot, 9agent.output)Sample output snippet
Spec reference
docs/incubation-docs/adapter-framework/04-per-framework-specs/04b-langchain-adapter-spec.md§1 weakness #4 and §4 (LCEL Support).