RunnableRails#
本指南将教您如何将使用 NeMo Guardrails 构建的 guardrail 配置集成到您的 LangChain 应用程序中。本指南中的示例将侧重于使用 LangChain 表达式语言 (LCEL)。
概述#
NeMo Guardrails 提供了一个 LangChain 原生接口,通过 RunnableRails
类实现了 Runnable 协议。要开始使用,您必须首先加载一个 guardrail 配置并创建一个 RunnableRails
实例
from nemoguardrails import RailsConfig
from nemoguardrails.integrations.langchain.runnable_rails import RunnableRails
config = RailsConfig.from_path("path/to/config")
guardrails = RunnableRails(config)
要在链中 LLM 模型周围添加 guardrails,您必须使用 RunnableRails
实例“包装” LLM 模型,即 (guardrails | ...)
。
让我们来看一个使用 prompt、模型和输出解析器的典型示例
from langchain.chat_models import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
model = ChatOpenAI()
output_parser = StrOutputParser()
chain = prompt | model | output_parser
要在上面的示例中在 LLM 模型周围添加 guardrails
chain_with_guardrails = prompt | (guardrails | model) | output_parser
注意
使用额外的括号对于强制执行 |
(管道) 运算符的应用顺序至关重要。
要将 guardrails 添加到现有链(或任何 Runnable
),您必须以类似的方式包装它
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
rag_chain_with_guardrails = guardrails | rag_chain
您还可以使用相同的方法仅在链的某些部分周围添加 guardrails。下面的示例(从 RunnableBranch 文档中提取)在 RunnableBranch
内的“anthropic”和“general”分支周围添加了 guardrails
from langchain_core.runnables import RunnableBranch
branch = RunnableBranch(
(lambda x: "anthropic" in x["topic"].lower(), guardrails | anthropic_chain),
(lambda x: "langchain" in x["topic"].lower(), langchain_chain),
guardrails | general_chain,
)
一般来说,您可以使用 guardrails 包装可运行链的任何部分
chain = runnable_1 | runnable_2 | runnable_3 | runnable_4 | ...
chain_with_guardrails = runnable_1 | (guardrails | (runnable_2 | runnable_3)) | runnable_4 | ...
输入/输出格式#
包装 LLM 模型时支持的输入/输出格式为
输入格式 |
输出格式 |
---|---|
Prompt (即 |
完成字符串 |
聊天记录 (即 |
新消息 (即 |
包装链(或 Runnable
)时支持的输入/输出格式为
输入格式 |
输出格式 |
---|---|
带有 |
带有 |
带有 |
字符串输出 |
字符串输入 |
带有 |
字符串输入 |
字符串输出 |
Prompt 直通#
guardrail 配置的作用是验证用户输入,检查 LLM 输出,指导 LLM 模型如何响应等等(有关不同类型 rails 的更多详细信息,请参阅配置指南)。为了实现这一点,guardrail 配置可能会额外调用 LLM 或其他模型/API(例如,用于事实核查和内容审核)。
默认情况下,当 guardrail 配置确定提示 LLM 是安全的时,它将使用作为输入提供的确切 prompt(即字符串、StringPromptValue
或 ChatPromptValue
)。但是,为了强制执行特定的 rails(例如,对话 rails、一般指令),guardrails 配置需要更改用于生成响应的 prompt。要启用此行为(提供更强大的 rails),您必须在创建 RunnableRails
实例时将 passthrough
参数设置为 False
guardrails = RunnableRails(config, passthrough=False)
带有 Guardrails 的链的输入/输出键#
当 guardrail 配置用于包装链(或 Runnable
)时,输入和输出可以是字典或字符串。但是,guardrail 配置始终对来自用户的文本输入和来自 LLM 的文本输出进行操作。为了实现这一点,当使用字典时,输入字典中的一个键必须被指定为“输入文本”,输出中的一个键必须被指定为“输出文本”。默认情况下,这些键是 input
和 output
。要自定义这些键,您必须在创建 RunnableRails
实例时提供 input_key
和 output_key
参数。
guardrails = RunnableRails(config, input_key="question", output_key="answer")
rag_chain_with_guardrails = guardrails | rag_chain
当 guardrail 被触发,并且必须返回预定义的消息时,将只返回一个带有 output 键的字典,而不是来自 LLM 的输出
{
"answer": "I'm sorry, I can't assist with that"
}
使用工具#
guardrail 配置还可以使用工具作为对话 rails 的一部分。以下代码片段使用 LLMMathChain
定义了 Calculator
工具
from langchain.chains import LLMMathChain
tools = []
class CalculatorInput(BaseModel):
question: str = Field()
llm_math_chain = LLMMathChain(llm=model, verbose=True)
tools.append(
Tool.from_function(
func=llm_math_chain.run,
name="Calculator",
description="useful for when you need to answer questions about math",
args_schema=CalculatorInput,
)
)
为了确保所有数学问题都使用此工具回答,您可以创建一个如下所示的 rail 并将其包含在您的 guardrail 配置中
define user ask math question
"What is the square root of 7?"
"What is the formula for the area of a circle?"
define flow
user ask math question
$result = execute Calculator(tool_input=$user_message)
bot respond
最后,您将 tools
数组传递给 RunnableRails
实例
guardrails = RunnableRails(config, tools=tools)
prompt = ChatPromptTemplate.from_template("{question}")
chain = prompt | (guardrails | model)
print(chain.invoke({"question": "What is 5+5*5/5?"}))
局限性#
RunnableRails
接口的当前实现不支持流式传输。这将在未来的版本中解决。