Langchain-core 统一运行协议 Runnable

2
image
1.思考:不用 Runnable,我们写链式代码会是什么样?

点击查看代码
def to_upper(s:str):
    return s.upper()

def add_suffix(s:str):
    return s + " --processed"

# 调用:一层一层嵌套
input_text = "hello world"
res1 = to_upper(input_text)
res2 = add_suffix(res1)
print(res2)
# HELLO WORLD --processed
#同步调用、异步调用、批量跑一堆输入、流式返回**,每个函数我都要自己手写 4 套逻辑

2.RunnableLambda:把普通函数包成 Runnable

点击查看代码
from langchain_core.runnables import RunnableLambda

def to_upper(s:str):
    return s.upper()

def add_suffix(s:str):
    return s + " --processed"

r_upper = RunnableLambda(to_upper)
r_suffix = RunnableLambda(add_suffix)

# 管道 | :把两个runnable拼接起来
chain = r_upper | r_suffix

# chain 本质就是 RunnableSequence
result = chain.invoke("hello world")
print(result) # HELLO WORLD --processed
# 执行 `r_upper | r_suffix`,触发 Runnable 内部的 `__or__`运算符,生成一个`RunnableSequence(steps=[r_upper, r_suffix])`对象。

image

other 类型 说明
Runnable[Any, Other] 已经是 Runnable 实例,直接用
Callable[[Any], Other] 普通同步函数 func(x) → 包装成 RunnableLambda
Callable[[Iterator[Any]], Iterator[Other]] 同步迭代器函数(流式处理)
Callable[[AsyncIterator[Any]], AsyncIterator[Other]] async 迭代器函数,适配流式输出
Mapping[str, ...] {"key": another_runnable}→ 生成RunnableParallel` 并行分支

3.RunnablePassthrough:透传

点击查看代码
from langchain_core.runnables import RunnableLambda, RunnablePassthrough

def upper_name(d:dict):
    return d["name"].upper()

chain = (
    RunnablePassthrough.assign(
        name_upper = RunnableLambda(upper_name)
    )
)

res = chain.invoke({"name":"alice"})
print(res)
# {'name': 'alice', 'name_upper': 'ALICE'}

4.RunnableMap,并行输出多个结果

点击查看代码
from langchain_core.runnables import RunnableLambda, RunnableMap

r_upper = RunnableLambda(lambda s: s.upper())
r_lower = RunnableLambda(lambda s: s.lower())

# RunnableMap:同一个输入,同时喂给多个runnable,输出字典
map_chain = RunnableMap({
    "origin": RunnableLambda(lambda x:x),
    "upper": r_upper,
    "lower": r_lower
})

res = map_chain.invoke("Hello")
print(res)
# {'origin': 'Hello', 'upper': 'HELLO', 'lower': 'hello'}

5.RunnableRouter,条件分支

点击查看代码
from langchain_core.runnables import RunnableLambda, RunnableRouter

r_even = RunnableLambda(lambda x: x + 1)
r_odd = RunnableLambda(lambda x: x * 2)

# router函数:接收输入,返回key,用来选择runnable
def route_func(num:int) -> str:
    if num % 2 == 0:
        return "even_key"
    else:
        return "odd_key"

router_chain = RunnableRouter(
    router=route_func,
    runnables={
        "even_key": r_even,
        "odd_key": r_odd
    }
)

print(router_chain.invoke(4)) # 偶数 4+1=5
print(router_chain.invoke(5)) # 奇数 5*2=10

6.RunnableConfig 运行时上下文

点击查看代码
#RunnableConfig 不是业务输入数据,是链路的附加环境信息,整条链路透传。
from langchain_core.runnables import RunnableLambda
from langchain_core.runnables.config import RunnableConfig

def show_config(x:int, config:RunnableConfig):
    print(f"拿到config: {config['tags']}")
    return x * 10

r = RunnableLambda(show_config)

cfg = RunnableConfig(tags=["test_demo"])
res = r.invoke(2, config=cfg)
# 打印:拿到config: ['test_demo']
print(res) #20

7.完整示例

点击查看代码
from langchain_core.runnables import (
    RunnableLambda, RunnablePassthrough, RunnableMap, RunnableRouter
)
from langchain_core.runnables.config import RunnableConfig

# 1.基础lambda
add1 = RunnableLambda(lambda x: x+1)
mul2 = RunnableLambda(lambda x: x*2)

# 2.路由分支
def rt_func(x):
    return "even" if x%2==0 else "odd"
router = RunnableRouter(
    router=rt_func,
    runnables={"even":add1, "odd":mul2}
)

# 3.整体管道:先路由,再做map并行输出
full_chain = router | RunnableMap({
    "raw_input": RunnableLambda(lambda x:x),
    "double": RunnableLambda(lambda x:x*100)
})

config = RunnableConfig(tags=["full_demo"])
out = full_chain.invoke(4, config=config)
print(out)
# raw_input = 5(4是偶数执行+1),double = 500

类/接口 作用
🅰️Runnable抽象类 规定所有组件必须有 invoke/ainvoke/batch...这一套接口
🅲RunnableLambda 把普通函数包装成标准 Runnable
🅲RunnableSequence `管道生成,顺序执行一组 runnable
🅲RunnablePassthrough 透传字典数据,.assign()追加字段
🅲RunnableBinding .bind()产生,包装绑定参数
🅲RunnableMap 同一个输入并行跑多个 runnable,输出字典
🅲RunnableRouter 根据输入做 if‑else 分支路由
🅲RunnableConfig 全链路透传的上下文环境对象,和业务数据分开
posted @ 2026-09-03 21:25  kofxx  阅读(1)  评论(0)    收藏  举报