LangChain Expression Language (LCEL): Xây dựng chuỗi LLM linh hoạt

LangChain Expression Language (LCEL) là giao diện khai báo chuẩn để xây dựng và tổ hợp chuỗi xử lý LLM trong hệ sinh thái LangChain. Thay vì viết logic lồng nhau thủ công, LCEL cho phép định nghĩa pipeline như một biểu thức tuyến tính, từ đó tận dụng được streaming, async, batch, fallback và retry tự động mà không cần code boilerplate.

Tại sao cần LCEL?

Trước LCEL, các nhà phát triển thường dùng LLMChain hoặc SequentialChain — các class kế thừa phức tạp, khó mở rộng, và streaming chỉ hoạt động ở tầng cuối. LCEL giải quyết bằng cách làm cho mọi thành phần (prompt, model, parser, retriever, tool) đều implements giao diện Runnable thống nhất. Kết quả: một chuỗi prompt | model | parser tự động hỗ trợ .stream(), .abatch(), .with_fallbacks() mà không cần viết thêm một dòng code.

Giao diện Runnable là trái tim của LCEL. Mọi component trong LangChain hiện nay — từ ChatPromptTemplate, ChatOpenAI, StrOutputParser đến custom retriever, tool, hay lambda function — đều implement interface này. Sự thống nhất này cho phép tổ hợp (composition) trở nên tự nhiên: output của Runnable này trở thành input của Runnable kia thông qua toán tử pipe |.

Sơ đồ pipeline LCEL prompt | model | parser với mũi tên luồng dữ liệu
Sơ đồ pipeline LCEL prompt | model | parser với mũi tên luồng dữ liệu

Ba phương thức cốt lõi của Runnable

Mọi Runnable trong LCEL tuân thủ ba phương thức chính:

  • invoke(input) — chạy đồng bộ, trả về kết quả cuối cùng
  • stream(input) — trả về async iterator cho token-by-token streaming
  • batch(inputs) — xử lý nhiều input cùng lúc, tận dụng concurrency pool

Ngoài ra còn có abatch (async batch), astream (async stream), with_config (gán metadata như run_name, tags), và with_fallbacks (chuỗi dự phòng khi thành phần chính lỗi). Tất cả các phương thức này đều được implement mặc định ở base class — developer chỉ cần implement invoke (hoặc stream nếu muốn tối ưu streaming).

Ví dụ: RAG chain hoàn chỉnh với LCEL

Đoạn code sau minh họa một chuỗi RAG (Retrieval-Augmented Generation) chuẩn production:

from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template(
    "Trả lời dựa trên ngữ cảnh:n{context}nnCâu hỏi: {question}"
)
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
parser = StrOutputParser()

# Retriever đã được cấu hình sẵn (vector store, similarity search)
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

rag_chain = (
    {"context": retriever | RunnableLambda(lambda docs: "nn".join(d.page_content for d in docs)),
     "question": RunnablePassthrough()}
    | prompt
    | model
    | parser
)

# Streaming token-by-token
for chunk in rag_chain.stream("Tóm tắt bài báo về LCEL"):
    print(chunk, end="", flush=True)

Chuỗi trên tự động: lấy tài liệu liên quan, ghép ngữ cảnh, đưa vào prompt, gọi model, parse output — và streaming hoạt động ngay từ lần đầu chạy. Lưu ý RunnablePassthrough() chuyển input gốc (câu hỏi) thẳng đến prompt, trong khi retriever | RunnableLambda(...) biến đổi kết quả tìm kiếm thành string ngữ cảnh.

Code snippet LCEL RAG chain với highlight các toán tử pipe
Code snippet LCEL RAG chain với highlight các toán tử pipe

Tổ hợp nâng cao: Parallel, Branching, Fallback

LCEL cho phép chạy song song nhiều nhánh và gom kết quả nhờ RunnableParallel:

from langchain_core.runnables import RunnableParallel

# Chạy song song: tóm tắt + trích xuất thực thể + phân loại chủ đề
analysis_chain = RunnableParallel(
    summary=prompt_summary | model | parser,
    entities=prompt_entities | model | parser,
    category=prompt_category | model | parser,
)

result = analysis_chain.invoke({"input": long_document})
# result = {"summary": "...", "entities": [...], "category": "..."}

Mỗi key trong RunnableParallel là một sub-chain độc lập. LCEL tự động chạy chúng song song (dùng thread pool) và gom kết quả thành dict. Điều này giảm latency đáng kể so với chạy tuần tự — ví dụ 3 lệnh gọi LLM song song mất ~2s thay vì ~6s.

Fallback chain đảm bảo độ bền: nếu model chính (gpt-4o) lỗi rate-limit, tự động chuyển sang model dự phòng (gpt-4o-mini):

robust_chain = (prompt | model).with_fallbacks([prompt | backup_model])

Khi chain đầu tiên raise exception, LCEL tự động thử chain kế tiếp trong danh sách fallback. Có thể chuỗi nhiều cấp: .with_fallbacks([chain2, chain3, chain4]).

LCEL vs LangGraph: Khi nào dùng cái nào?

LCEL phù hợp cho pipeline tuyến tính, đơn hướng, không cần state phức tạp. LangGraph (cùng tác giả LangChain) thiết kế cho workflow có vòng lặp, điều kiện, human-in-the-loop, và state persistence. Quy tắc đơn giản: nếu chuỗi xử lý có thể vẽ thành đường thẳng — dùng LCEL; nếu là đồ thị có chu trình — dùng LangGraph.

Ví dụ LCEL đủ dùng: RAG chain, summarization pipeline, structured output extraction, tool calling sequence. Ví dụ cần LangGraph: ReAct agent (think-act-observe loop), multi-agent debate, workflow cần checkpoint/resume, human approval step.

Triển khai production: LangServe

LCEL chain có thể expose thành REST API chỉ trong vài dòng code nhờ langserve:

from langserve import add_routes
from fastapi import FastAPI

app = FastAPI()
add_routes(app, rag_chain, path="/rag")

# Chạy: uvicorn main:app --reload
# Test: curl -X POST http://localhost:8000/rag/invoke -d '{"input": "Câu hỏi"}'

API tự động có endpoint /invoke, /stream, /batch, /stream_log — sẵn sàng cho frontend consume streaming SSE. stream_log đặc biệt hữu ích: trả về intermediate step (retriever result, prompt sent, model raw output) bên cạnh final answer — tuyệt vời cho debugging và observability.

Config và Observability

with_config cho phép gán metadata cho chain, sau đó dùng trong LangSmith tracing:

chain = (prompt | model | parser).with_config(
    run_name="rag_chain_v2",
    tags=["production", "rag"],
    metadata={"version": "2.1", "team": "ml-platform"}
)

Kết hợp với langsmith tracing: mọi run tự động log input/output, latency, token usage, error — hỗ trợ A/B testing prompt, model, retriever config mà không cần custom logging.

Tóm tắt

LCEL đưa LangChain từ framework “viết chain tùy chỉnh” thành ngôn ngữ tổ hợp chuẩn cho LLM pipeline. Ưu điểm lớn: streaming tự động, async native, fallback declarative, và deploy API zero-config qua LangServe. Với bất kỳ dự án nào dùng LangChain hiện nay, LCEL là cách viết chain được khuyến nghị mặc định.

Nguồn: LangChain LCEL Documentation | LangChain GitHub

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

So sánh tốc độ và RAM usage của Phi-3.5-mini, Gemma 2 2B, Qwen2.5 3B trên Raspberry Pi 5

So sánh SLM trên thiết bị biên Phi-3.5-mini Gemma 2 2B Qwen2.5 3B

Giới thiệu về Small Language Models (SLMs) Small Language Models (SLMs) đang trở thành xu hướng mới trong lĩnh vực AI cho thiết bị biên (Edge AI) với kích thước…

Xem thêm

RAG là gì: Retrieval Augmented Generation cho AI hiện đại

RAG: Retrieval Augmented Generation nâng cấp LLM RAG (Retrieval Augmented Generation) là kỹ thuật kết hợp truy xuất tài liệu từ cơ sở tri thức bên ngoài với khả năng…

Xem thêm

TinyML: Chạy Machine Learning Trên Vi Điều Khiển Siêu Nhỏ

TinyML là gì? TinyML là nhánh trí tuệ nhân tạo intelligence chạy trực tiếp trên vi điều khiển siêu nhỏ — những chip có RAM chỉ vài KB, không cần…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất