langchain学习笔记——runnable接口

一、 runnable接口函数

invoke:将单个输入转换为输出

batch:将多个输入转换为输出

stream:流式输出

二、runnable组件  

2.1 组件种类

2.2 runnable组件的动态参数绑定

动态绑定:在运行时确定参数与函数的映射关系,而不是在编写代码时固定

1、将函数附加到模型上

#符合openai functions规范的函数声明:json schema格式
functions=[
    {
        "name": "solver",
        "description": "Formulates and solves an equation",
        "parameters": {
            "type": "object",
            "properties": {
                "equation": {
                    "type": "string",
                    "description": "The algebraic expression of the equation",
                },
                "solution": {
                    "type": "string",
                    "description": "The solution to the equation",
                },
            },
            "required": ["equation", "solution"],
        },
    },
    {
        "name": "birth_finder",
        "description": "Finds the birth city and the birth date of the person",
        "parameters": {
            "type": "object",
            "properties": {
                "city":{
                    "type":"string",
                    "description":"the birth place of the person",
                },
                "date":{
                    "type":"string",
                    "description":"the birth date of the person"
                }
            },
            "required": ["city","date"],
        },
    },
]

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Please provide the birth city and the birth date of the following person:",
        ),
        ("human", "{person}"),
    ]
)

model = ChatOpenAI(model="gpt-4", temperature=0,api_key="",base_url="").bind( 
    function_call="auto", functions=functions
)
runnable = {"person": RunnablePassthrough()} | prompt | model
output = runnable.invoke("Barack Obama")
print(output)
  • functions参数提供了一个函数列表,其中每个函数都有一个名称和参数描述。这个列表告诉模型有哪些函数可以调用,以及每个函数需要什么参数。

  • function_call参数指定了在生成文本的过程中应该调用哪个函数。它是一个包含函数名称的字典,模型会根据这个名称来选择要调用的函数。而auto则模型会根据自己的生成自动选择要调用的函数

  • 解释:为什么传递的参数是person,但函数需要的参数是city和date:birth_finder 函数的作用是接收已经生成或解析出的 citydate 参数,然后根据这些参数执行某种处理,或者只是按照特定的格式返回结果。它并不会主动解析或生成这些信息,而是依赖于模型在之前的步骤中已经生成的内容

三、runnable对象类型

runnable对象类型,指明了runnable组件之间的数据流动方式

3.1 RunnableLambda

参数:func

  • 描述: 这是传递给 RunnableLambda 的函数或 lambda 表达式。它定义了如何处理传入的数据
sequence = RunnableLambda(lambda x: x + 1) | {
    'mul_2': RunnableLambda(lambda x: x * 2),
    'mul_5': RunnableLambda(lambda x: x * 5)
}
print(sequence.invoke(1))
#{'mul_2': 4, 'mul_5': 10}
sequence2 = RunnableLambda(lambda x: x + 1) | RunnableLambda(lambda x: x * 2)|RunnableLambda(lambda x: {"outcome":x * 5})
print(sequence2.invoke(1))
#{'outcome': 20}

3.2 RunnablePassthrough

数据流动方式:直接传递

不传输全部数据:itemgetter:传递字典中的某一个键值

3.3 RunnableSequence

  • 数据流动方式:按顺序链式处理

  • 说明:在 RunnableSequence 中,数据按顺序从第一个 runnable 组件流向第二个,依此类推

  • 创建方式:

    • 显示创建:RunnableSequence(step1, step2),其中step1、step2应该为a Runnable, callable or dict

    • 隐式创建:用|串联

3.4 RunnableMap (RunnableParallel,同名)

用词典嵌入sequence即相当于构建了runnableparallel,没什么特别的,就是使用相同参数填充value罢了

3.4.1 书写格式

RunnableParallel({"key1":value1, "key2":value2})

  • 字典的每个属性(key1与key2)都接受相同的输入参数
  • 而后使用这些参数并行调用value1、value2,返回值用于填充map对象
  • 将填充完数据的字典对象传递给sequence中的下一个runnable对象

3.4.2 用法

1.并行调用runnable对象或函数

# 并行处理runnable对象
model= ChatOpenAI(model="gpt-4", temperature=0,api_key="",base_url="")

joke_chain = ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
poem_chain = (
    ChatPromptTemplate.from_template("write a 2-line poem about {topic}") | model
)

map_chain = RunnableParallel({"joke":joke_chain, "poem":poem_chain})
print(map_chain.invoke({"topic": "bear"}))
#并行处理函数
def task1(x):
    # 执行一些操作
    return x+1

def task2(x):
    # 执行一些操作
    return x+2

# 创建 RunnableParallel 实例
parallel_executor = RunnableParallel({"1":task1,"2":task2})
print(parallel_executor.invoke(3))

2. 自动实现runnable对象间的输入——输出格式转换

vectorstore = FAISS.from_texts(
    ["harrison worked at kensho"], embedding=OpenAIEmbeddings()
)
# 定义了一个检索器 retriever,可以从文本中检索上下文
retriever = vectorstore.as_retriever()  
# template 定义了一个带占位符的prompt模板,所以prompt组件需要一个包含context和question键的字典作为输入。
template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

retrieval_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

retrieval_chain.invoke("where did harrison work?")

说明:

prompt组件需要一个包含"context"和"question"键的字典作为输入。

用户只输入了一个问题字符串。

于是使用了一个RunnableMap,组装context与question得到prompt组件需要的输入格式

3. 构建复杂链

prompt1 = ChatPromptTemplate.from_template('what is the city {person} is from?only respond with city name.')
prompt2 = ChatPromptTemplate.from_template('What country is the city {city} in? Respond in {language}.')

combinedChain={"city":itemgetter("person")|prompt1|model|StrOutputParser(),"language":itemgetter("language")}|prompt2|model|StrOutputParser()
result=combinedChain.invoke({"person":"chairman Mao","language":"chinese"})
print(result)
即询问毛主席来自哪个城市——>这座城市属于哪个国家,用中文回答
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值