- NLP
- 人工智能
- 深度学习
【免费下载链接】ParlAI
A framework for training and evaluating AI models on a variety of openly available dialogue datasets.
Local Human Agent(local_human)是 ParlAI 框架内置的一个特殊 Agent:它不在本地执行任何模型推理,而是把"人类用户"接入对话循环——在act()函数里读取命令行键盘输入,作为对话中的一方参与parley()回合。本文以 parlai/agents/local_human/README.md 为骨架,结合 local_human.py、interactive.py、safe_local_human.py 等源码,系统讲解它的工作原理、命令行参数、控制指令、源码级调用链与安全增强用法,帮助读者掌握在 ParlAI 中"人机对话"的完整实践方案。
文中图片来自仓库 projects/bb3/anim.gif,示意 ParlAI 支持基于命令行文本的交互式人机对话场景。
什么是 Local Human Agent
Local Human Agent 是 ParlAI 中的一个 Agent 实现,类名为LocalHumanAgent,位于 parlai/agents/local_human/local_human.py。它与常规模型 Agent 的本质区别在于:
- 不加载任何模型权重:它自身不做推理,只负责采集人类输入;
- 输入源是命令行:在
act()阶段通过 Python 内置的input()读取键盘输入; - 扮演对话中的"人类"角色:在
World.parley()中与另一个模型 Agent 轮流发言,模型 Agent 收到它产出的Message后正常推理回复。
该 Agent 的核心用途是支撑 ParlAI 的interactive脚本(parlai/scripts/interactive.py),实现"本地人类 + 预训练模型"的命令行实时对话。README 中给出了最简单的用例:
python projects/personachat/scripts/kvmemnn_interactive.py该命令会启动一个针对 Persona-Chat 数据训练的 KVMemNN 模型的交互式会话(该示例源自 projects/personachat/README.md 中 "Interact with a pre-trained Key-Value Memory Net model trained on Persona-Chat using persona 'self'" 一节)。需要注意的是,personachat 项目已于 2020-08-01 归档,模型与脚本长期未测试;README 建议如需使用模型或脚本,回退到对应的personachat标签,而 Persona-Chat 数据集本身仍可正常使用(--task personachat)。
核心实现:act() 中的键盘输入逻辑
LocalHumanAgent继承自 ParlAI 基类Agent(parlai/core/agents.py),其对话逻辑全部浓缩在三个关键方法中。
初始化与状态
在__init__中(local_human.py#L45-L56):
- 设置
self.id = 'localHuman',作为 Message 中的发送者标识; - 初始化
episodeDone = False、finished = False两个状态标志; - 通过
load_cands加载固定候选回复文件(对应--local-human-candidates-file参数); - 启动时打印一行提示:
Enter [DONE] if you want to end the episode, [EXIT] to quit.(使用colorize高亮)。
load_cands是 parlai/utils/misc.py#L122-L156 中的通用工具:它逐行读取候选文件,自动去除行号前缀(当首行以1开头时判定lines_have_ids)、按 Tab 拆分(当行内含 Tab 时按"回复列"提取label_candidates),并把\n转义还原为真实换行。
observe:把对方消息打印到终端
observe方法(local_human.py#L61-L69)接收模型 Agent 的回复 Message,并调用display_messages格式化输出。display_messages定义于 parlai/utils/misc.py#L491,它支持:
- 多消息渲染与双人对话缩进(第二条消息前追加空格);
prettify=True时用 prettytable 展示候选文本(label_candidates);verbose=True时显示id、text、labels、label_candidates等全部字段;add_fields追加展示自定义字段,如token_losses(生成模型逐 token 的 loss,可用于调试生成模型,见 TorchGeneratorAgent._construct_token_losses 相关实现)。
act:读取键盘并构造回复
act方法(local_human.py#L71-L92)是核心:
def act(self): reply = Message() reply['id'] = self.getID() try: reply_text = input(colorize("Enter Your Message:", 'text') + ' ') except EOFError: self.finished = True return {'episode_done': True} reply_text = reply_text.replace('\\n', '\n') reply['episode_done'] = False if self.opt.get('single_turn', False): reply.force_set('episode_done', True) reply['label_candidates'] = self.fixedCands_txt if '[DONE]' in reply_text: # let interactive know we're resetting raise StopIteration reply['text'] = reply_text if '[EXIT]' in reply_text: self.finished = True raise StopIteration return reply关键行为包括:
- EOF 处理:当用户按下 Ctrl-D(
input()抛EOFError)时,设置finished = True并返回{'episode_done': True}结束会话; - 换行转义:输入中的字面
\n会被替换为真实换行,支持多行消息; - 单轮模式:
single_turn=True时强制episode_done=True,即每个输入都视为独立回合; - 候选注入:
label_candidates始终携带--local-human-candidates-file指定的固定候选列表(若有),供另一侧模型做候选排序; - 控制指令:输入包含
[DONE]时抛StopIteration通知世界层"重置本轮"(不开新 episode 标志);包含[EXIT]时置finished = True再抛StopIteration,永久退出。
回合与轮次终止
episode_done()返回self.episodeDone,本 Agent 自身一般不主动结束回合(默认False);epoch_done()返回self.finished,用于驱动外层while not world.epoch_done()循环退出。
命令行参数
LocalHumanAgent.add_cmdline_args(local_human.py#L22-L43)注册了两个参数:
| 参数 | 别名 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
--local-human-candidates-file | -fixedCands | str | None | 候选回复文件路径,其内容会作为label_candidates发送给对面的模型 Agent |
--single_turn | — | bool | False | 开启后假定每个输入都是单轮 episode(强制episode_done=True) |
此外,与 Local Human Agent 配套使用的展示类参数由interactive脚本在 interactive.py#L32-L75 中统一注册:
-d / --display-examples(bool,默认False):每回合后打印完整world.display();--display-prettify(bool,默认False):候选文本用 prettytable 展示;--display-add-fields(str,默认''):verbose 关闭时追加展示的字段,例如--display-add-fields label_candidates,beam_texts;-it / --interactive-task(bool,默认True):创建任务的交互版本(对话历史按轮次传递);--outfile(str,默认''):把全部轮次写入 jsonl 日志文件;--save-format(str,默认conversations,可选conversations/parlai):日志格式,conversations 为 jsonl,parlai 为文本格式。
这些参数与 Local Human Agent 的参数一同被setup_args注入ParlaiParser,因此parlai interactive命令行可以直接使用。
与 interactive 脚本的完整调用链
LocalHumanAgent最常见的启动入口是parlai interactive(注册名为interactive,别名i,见 interactive.py#L111-L118)。其核心流程在interactive(opt)函数(interactive.py#L78-L108)中:
- 创建模型 Agent:
create_agent(opt, requireModelExists=True)加载用户通过--model-file(或-mf)指定的预训练模型; - 创建人类 Agent:
human_agent = LocalHumanAgent(opt); - 创建世界:
create_task(opt, [human_agent, agent])把人类 Agent 与模型 Agent 配对;interactive脚本默认task='interactive'且interactive_mode=True,即构建一个"交互版"任务世界(见 parlai/core/worlds.py 中create_task对interactive_mode的处理); - 对话循环:
while not world.epoch_done(): world.parley()。每轮parley()中,模型 Agent 先生成回复,人类 Agent 的observe打印该回复;随后人类 Agent 的act()读取键盘输入产出消息,模型 Agent 收到后再回复。如此往复; - 控制流处理:当人类输入
[DONE]或[EXIT]触发StopIteration时,世界层重置对话(world_logger.reset()清除已记录的日志,若配置了日志);EOF(Ctrl-D)则直接结束epoch_done; - 日志落盘:若设置了
--outfile,循环结束后world_logger.write(opt['outfile'], world, file_format=opt['save_format'])把全部对话写入文件。
一个典型的启动命令(来自 interactive.py#L12 的 docstring):
parlai interactive --model-file "zoo:tutorial_transformer_generator/model"运行时按提示输入消息(例如Bob is Blue.\nWhat is Bob?)。注意输入内容往往与任务相关:使用-t convai2时任务会自动为模型附带 persona 上下文。
测试证据:tests/test_interactive.py 通过mock.patch('builtins.input', new=FakeInput())替换input(),用确定性的假输入(Turn 1、Turn 2、[DONE]、[EXIT]/EOFError)驱动Interactive.main(model='repeat_query')与SafeInteractive.main(model='repeat_query'),验证了[DONE]/[EXIT]/EOF 三种退出路径以及--outfile日志的长度与内容(TestInteractiveLogging断言len(log) == max_episodes、每条len(entry) == 2 * max_turns,即每回合恰好两轮发言)。
实战:与预训练模型命令行对话
除parlai interactive外,仓库中的项目脚本也大量使用 Local Human Agent 实现人机对话。例如 convai2 项目的 README(projects/convai2/README.md#L43-L55)给出:
python projects/convai2/interactive.py -mf models:convai2/kvmemnn/model以及更换模型为 seq2seq 的写法:
python projects/convai2/interactive.py -mf models:convai2/seq2seq/convai2_self_seq2seq_model -m legacy:seq2seq:0从源码结构看,这些交互脚本同样遵循"LocalHumanAgent+ 预训练模型 + 配对世界"的模式。此外,-m local_human也可以作为通用模型参数使用,例如 README docstring 中给出的:
parlai eval_model -m local_human -t babi:Task1k:1 -dt valid即以本地键盘输入作为模型来"评测"一个任务数据集——每轮从终端读取回复充当模型输出,便于人工检查数据集与评测流程。
运行前提:parlai interactive与上述项目脚本都要求先安装 ParlAI 及其依赖(见 setup.py、requirements.txt),且--model-file指向已下载的预训练模型;zoo:前缀的模型由 parlai/zoo 中的下载脚本自动拉取。交互体验依赖终端是否为 TTY:colorize只在 stdout 连接终端(或处于 IPython 环境)时输出 ANSI 彩色样式,可通过环境变量PARLAI_COLORSTYLE调整配色方案(parlai/utils/strings.py#L76-L119)。
安全增强:SafeLocalHumanAgent
在纯命令行交互之上,仓库还提供了带安全过滤的变体SafeLocalHumanAgent(parlai/agents/safe_local_human/safe_local_human.py),通过parlai safe_interactive脚本(parlai/scripts/safe_interactive.py)启动。它继承LocalHumanAgent,在保留键盘输入机制的同时,对人类输入与模型回复双向做冒犯性语言检测。
安全参数
safe_interactive脚本会注册SafeLocalHumanAgent.add_cmdline_args(safe_local_human.py#L29-L45),其独有参数为:
| 参数 | 类型 | 默认值 | 可选值 | 说明 |
|---|---|---|---|---|
--safety | str | all | none、string_matcher、classifier、all | 选择安全过滤方式:仅词表匹配、仅分类器、或两者全开 |
双向检测机制
初始化时(_init_safety,safe_local_human.py#L52-L61)按--safety加载两类检测器:
OffensiveStringMatcher(parlai/utils/safety.py#L82):基于公开的冒犯性词/短语清单(来自 LDNOOBW 数据集)做字面匹配,首次使用会自动构建数据;OffensiveLanguageClassifier(parlai/utils/safety.py#L19):加载zoo:dialogue_safety/single_turn/model预训练 Transformer 分类器,对单轮对话语句做冒犯性判别(训练数据含人类对抗样本,详见 parlai/utils/safety.py docstring 指向的 Dialogue Safety 项目)。
对话过程中:
- 人类输入被判定冒犯(
act中check_offensive(reply_text)为真):打印[ Sorry, could not process that message. Please try again. ]并循环要求重新输入,同时置self_offensive = True,使observe忽略模型对冒犯输入的回复; - 模型回复被判定冒犯(
observe中check_offensive(msg.get('text', ''))为真):打印[ Unsafe model reply detected. Clearing agent history. Please try again. ]并给消息打上bot_offensive=True标记,safe_interactive主循环检测到该标记后调用agent.reset()清空模型历史(safe_interactive.py#L60-L72); - 空文本直接视为安全,
bot_offensive=False正常放行。
控制指令[DONE]/[EXIT]的语义与LocalHumanAgent一致([DONE]或single_turn时抛StopIteration重置回合,[EXIT]额外置finished=True)。
小结
Local Human Agent 是 ParlAI"人在回路"交互的基础设施:
- 机制层面:通过
act()读取键盘输入、observe()打印对方消息、[DONE]/[EXIT]/EOF 控制回合与退出,与interactive/safe_interactive脚本及配对世界构成完整的人机对话闭环; - 参数层面:
--local-human-candidates-file注入固定候选、--single_turn强制单轮,展示与日志参数(--display-*、--outfile、--save-format)均由脚本层统一提供; - 扩展层面:
SafeLocalHumanAgent以继承方式叠加双向安全过滤,--safety可选词表匹配、分类器或全开,为敏感场景提供了开箱即用的防线。
无论是快速试玩zoo预训练模型、人工评测任务数据集,还是构建带安全护栏的评测环境,local_human都是 ParlAI 命令行交互体系中值得优先掌握的一环。
- NLP
- 人工智能
- 深度学习
【免费下载链接】ParlAI
A framework for training and evaluating AI models on a variety of openly available dialogue datasets.
相关推荐
PocketFlow 命令行笑话生成器:基于 Human-in-the-Loop 的交互式 Agent 流程实战
PocketFlow 命令行笑话生成器:基于 Human in the Loop 的交互式 Agent 流程实战 本篇技术指南以 PocketFlow 仓库 c
人工智能大模型AI Agent工作流自动化RAGParlAI Docker 镜像使用指南:一键拉起对话模型训练与交互环境
ParlAI Docker 镜像使用指南:一键拉起对话模型训练与交互环境 ParlAI 官方提供开箱即用的 Docker 镜像,内置已安装好的 ParlAI 框
NLP人工智能深度学习ParlAI 中的 K2R 模块化知识对话模型:先推理、后回复的训练、评估与交互实战
ParlAI 中的 K2R 模块化知识对话模型:先推理、后回复的训练、评估与交互实战 导读 K2R(Knowledge to Response)是 ParlAI
NLP人工智能深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考