我们将深入剖析项目背后的技术栈,涵盖索引储存、检索推理、安全审查三大核心版块。今天,我们率先聚焦于安全审查版块。
熟悉大模型的朋友都知道,其生成内容本质上是基于概率的单字接龙模式,这就导致生成结果存在不确定性。而且,由于训练或微调过程往往并非我们亲自操作,若训练数据中不慎混入不当内容,大模型的回复极有可能出现问题。
一旦大模型生成与产品无关,甚至涉及政治敏感、色情、攻击性等不良内容,产品将面临下架风险,严重损害公司形象。因此,确保大模型生成指定的、安全的内容,就如同为产品系上 “安全带”,至关重要。
在安全审查方案方面,我们拥有众多选择,甚至可以根据业务流程进行定制开发。本次,我将为大家分享英伟达的开源项目框架 NeMo-Guardrails,其官方仓库地址为:https://github.com/NVIDIA/NeMo-Guardrails 。
后续,我会详细拆解该框架的功能、配置方法以及实际应用场景。本系列内容共分为两部分:
人的专注力有限,话不多说,接下来我们正式进入英伟达 NeMo-Guardrails 的学习。
一、NeMo-Guardrails 有什么用?
NeMo-Guardrails 的核心作用是规避大模型生成风险内容,提升生成质量。与大模型进行过交互的人都清楚,即使用户发送相同的问题,在不同时间得到的回复也可能不同。
在正常对话中尚且如此,若遭遇专门的对话攻击,大模型将面临巨大风险。
因此,我们必须杜绝大模型生成不良和有风险的内容,同时也要避免误判优质、真实的内容,就像杀毒软件不能出现误杀情况一样。
英伟达的安全审查模块是一个极为全面的 LLM 安全工具集,它提供了广泛的可编程护栏,能够对 LLM 的输入和输出进行有效控制和指导,具体包括以下几个方面:
内容审核
严格审查生成内容,防止出现不良信息。
主题指导
将对话引导至特定主题,确保对话方向符合预期。
幻觉预防
减少事实不正确或无意义内容的生成,提升内容的可靠性。
为了让大家更清晰地理解其工作流程,我们来看一下它的四个轨道:
输入轨道(Input rails)
作用于用户输入,可拒绝输入、停止进一步处理,或对输入进行修改,例如隐藏敏感信息或改写内容。
对话轨道(Dialog rails)
影响发送给 LLM 的提示,决定是否执行动作、召唤 LLM 进行下一步操作或回复,以及选择预定义答案。
执行轨道(Execution rails)
应用于 LLM 调用自定义动作(工具)的输入和输出,确保动作执行的安全性和准确性。
输出轨道(Output rails)
对 LLM 生成的输出进行处理,可拒绝输出、阻止其发送给用户,或修改输出内容,删除敏感数据。
后续,我将结合 llamaindex 项目进行实际测试,验证其对输入输出的拦截效果。接下来,我们深入了解一下实现这些功能背后的四个关键模块。
二、NeMo-Guardrails 如何工作?四大模块分工详解
2.1 config.yml:总开关,掌控全局配置
config.yml 是整个项目中最为关键的模块,它就像一个总开关,控制着项目的整体配置。下面我们通过具体代码来了解其配置内容:
models
用于指定项目中使用的模型名称。官方已针对大部分模型进行了提示优化,支持 chat model 和 Embeddings Model。若模型不在官方列表中,也可进行自定义配置,详细的自定义及深入配置方法可参考:https://github.com/NVIDIA/NeMo-Guardrails/blob/develop/docs/user_guides/configuration-guide.md 。
instructions
定义通用指令,类似于系统提示,会在每个提示的开头添加,用于指导模型的回答方向。
sample_conversation
通过示例对话,在用户和机器人之间建立对话语气,帮助 LLM 理解响应的格式和对话风格,此部分至少需要包含两轮对话。
rails
定义护栏规则,分别设置了输入和输出轨,在该文件中定义的导轨将被激活,用于规范输入输出内容。
2.2 prompts.yml:审核员,严格把控输入输出
prompts.yml 就像一位审核员,主要用于控制输入输出内容。我们来看具体的代码示例:
这两个提示主要用于内容审核,通过设定明确的政策规则,确保能够有效阻止来自用户或机器人的攻击性输入和输出内容。
2.3 actions.py:指导员,灵活控制外部响应
actions.py 是一种特殊的可编程规则,它如同一位指导员,主要用于定义大型语言模型的特定行为或响应,其核心功能并非过滤不需要的话题,而是确保代码安全、可靠地执行,具体体现在以下三个方面:
触发响应
能够根据特定条件或输入,触发 LLM 的特定响应,允许定义除静态响应之外的自定义逻辑,实现更加灵活的交互效果,这也是我所说的 “会呼吸的 RAG”。
调用外部服务
将 LLM 与外部服务(如数据库、API、其他工具或框架)进行连接,打破信息孤岛,为 LLM 赋予更强大的功能。在下一篇内容中,我将通过 llamaindex 实跑,展示其具体应用。
控制对话流程
引导对话朝着指定方向进行,通过提示特定问题或避免不必要的题外话,实现对对话的有效管理。
更多详细的配置内容,可参考:https://github.com/NVIDIA/NeMo-Guardrails/blob/develop/docs/user_guides/python-api.md#actions 。
下面以会员实际项目的代码为例,为大家展示其具体编写方式:
在这段代码中:
init 函数
负责加载源文档,定义 LlamaPack,构建 RAG 管道的高级查询,并获取和缓存查询引擎。
get_query_response 函数
根据传入的 query_engine 和 query,检索相关节点,并将其传递给 LLM,最终生成响应结果。
user_query 函数
从上下文(context)中获取用户消息(user_message),打印消息内容后,初始化查询引擎,并调用 get_query_response 函数获取响应结果并返回。
2.4 bot_flows.co:自检员,实现输入输出自我检查
bot_flows.co 使用 Colang 这种建模编程语言来定义轨道流,它将前面配置好的各个步骤进行整合与实现,主要包括以下几个流程:
输入自我检查
执行内置操作,若检测到用户输入不符合规则,指示机器人拒绝响应,并停止对当前用户请求的进一步处理,对应操作:self_check_input。
输出自我检查
负责处理输出审查工作,同样通过 self_check_output 操作来判断输出内容是否合规,若不合规则拒绝响应。
用户查询自定义
执行自定义操作,与 LlamaIndex 集成,实现高级检索和内容生成功能,对应操作:user_query。
通过这些流程,我们能够灵活地控制 LLM 的行为和响应,实现复杂的对话管理和内容生成。具体代码如下:
领取专属 10元无门槛券
私享最新 技术干货