2026/9/24 15:50:46

ParlAI Message 详解:理解 Agent 之间 act() 与 observe() 的信息载体

ParlAI Message 详解:理解 Agent 之间 act() 与 observe() 的信息载体 NLP人工智能深度学习【免费下载链接】ParlAIA framework for training and evaluating AI models on a variety of openly available dialogue datasets.项目地址https://gitcode.com/gh_mirrors/pa/ParlAI点击查看免费下载Message 是 ParlAI 中信息流转的核心载体——它是 Agent 与环境或其他 Agent之间传递的 Pythondict子类承载对话文本、监督标签、候选答案、奖励、图像等所有数据。本文以 docs/source/core/messages.md 为骨架结合parlai/core/message.py及教师Teacher、世界World、Torch Agent 的源码实现系统讲解 Message 的标准字段、可变性保护机制、扩展字段约定与底层原理帮助你正确编写任务 Teacher、理解训练/评估数据流并为模型做多任务迁移做好准备。一、Message 是什么Observation 与 Act 的统一载体在 ParlAI 中Agent 与环境之间的一切交互都以消息Message的形式进行。官方文档将其定义为The primary medium for information flow (messages between agents and the environment) in ParlAI is a Message, a subclass of a pythondictcontaining the actions of an agent (observable by other agents or the environment).即Message 是信息流动的主要媒介是一个dict的子类其中包含某个 Agent 的动作action该动作可被其他 Agent 或环境观察到。ParlAI 中通常把这类消息称为observation观察或act动作。一个 Message 应由 Agent 的act()函数创建它会被作为唯一参数传递给另一个 Agent 的observe()函数。在源码 parlai/core/agents.py 中Agent基类对这两个方法给出了约定def observe(self, observation): Receive an observation from another agent or the environment. self.observation observation return observation def act(self): Produce an action from the agent. raise NotImplementedError(Must implement act function in your agent)世界的执行循环则负责把这二者串起来。以 parlai/core/worlds.py 中的DialogPartnerWorld为例acts[0] agents[0].act() agents[1].observe(validate(acts[0])) acts[1] agents[1].act() agents[0].observe(validate(acts[1]))可以看到Agent 0 的act()产出被validate校验后作为 Agent 1 的observe()输入反之亦然——这就是 Message 在对话双方之间“来回传递”的完整闭环。在MultiAgentDialogWorldparlai/core/worlds.py中每个 Agent 收到的则是自其上次act()以来所有其他 Agent 的动作。需要特别说明的是创建自己的任务时大多数字段是可选的。但存在一批标准字段在发送相应类型的数据时应当使用它们。这样做的直接收益是在一个数据集上训练好的模型可以很容易地迁移到另一个任务甚至进行多任务联合训练。二、Message 的可变性保护force_set与 RuntimeErrorMessage对象的核心功能是确保 Agent 不会无意中修改 observation 和 act 中的字段。在 parlai/core/message.py 中Message重写了dict的__setitem__class Message(dict): def __setitem__(self, key, val): if key in self: raise RuntimeError( Message already contains key {}. If this was intentional, please use the function force_set(key, value)..format(key) ) super().__setitem__(key, val) def force_set(self, key, val): super().__setitem__(key, val)也就是说对已存在的键再次赋值如message[text] new会抛出RuntimeError若确有需要覆盖字段必须显式调用message.force_set(key, new_value)Message.copy()返回的是同类型的Message对象type(self)(self)因此复制品依然保留同样的写保护语义。这一机制在框架内部被广泛使用。例如教师通过action.force_set(id, self.getID())写入发送者 IDparlai/core/teachers.pyTorch Agent 在向量化时用obs.force_set(text_vec, ...)、obs.force_set(label_original_length, ...)写入派生字段parlai/core/torch_agent.py——这些都是“字段已存在但需要更新”的典型场景。测试 tests/test_messages.py 直接验证了这一契约message Message() message[text] lol try: message[text] rofl # 期望抛出 RuntimeError except RuntimeError as e: err e assert err is not None, Message allowed override message_copy message.copy() assert type(message_copy) Message, Message did not copy properly另外Message还提供了两个与批量训练/服务化相关的工具方法parlai/core/message.pypadding_example()构造一个用于 batch padding 的消息含batch_padding: True与episode_done: Trueis_padding()判断消息是否为 padding 示例json_safe_payload()剥离如metrics等不安全字段后转成普通dict供聊天服务chat-services、外部库或 Mephisto 交付使用。三、标准字段逐一详解1.text最标准的字段text是 observation dict 中最标准的字段包含从一个 Agent 发送给其他 Agent 的字符串文本。{ text: Hi! How are you?, }在 parlai/core/agents.py 的Agent.respond()便捷方法中可以看到它的核心地位respond()接收一个字符串或 Message强制要求消息中必须包含text字段否则抛RuntimeError随后克隆 Agent、调用observe()act()并返回response[text]。batch_respond()对批量消息也做了同样的text字段校验。2.id发送者的自标识id字段存放发送者的自我标识字符串。例如任务会用它来标记任务名使用--task squad时发出的消息id即为squad。在FixedDialogTeacher.process_action()中教师会统一用action.force_set(id, self.getID())写入该字段parlai/core/teachers.pygetID()默认来自opt.get(task, teacher)parlai/core/teachers.py因此消息的id与任务名天然对应。3.labels监督学习的目标当进行监督学习时labels字段存放合适的标签。对许多任务而言它只有一个回答但部分数据集支持多个正确答案因此该字段应是一个可迭代对象如 list、tuple而非字符串。{ text: What movies are about ginger rogers?, labels: [Top Hat, Kitty Foyle, The Barkleys of Broadway], }在 Torch Agent 的向量化流程_set_label_vec()parlai/core/torch_agent.py中可以看到若labels存在则优先取labels否则取eval_labels当标签多于一个时会随机挑选一个用于训练label lbls[0] if len(lbls) 1 else self.random.choice(lbls)。4.eval_labels验证/测试阶段的标签在验证validation和测试testing阶段labels字段会被移动到eval_labels以防止模型无意中在评估数据上训练。其转换逻辑位于 parlai/core/teachers.pyself.lastY action.get(labels, action.get(eval_labels, None)) if not DatatypeHelper.is_training(self.datatype) and labels in action: # move labels to eval field so not used for training # but this way the model can use the labels for perplexity or loss action action.copy() labels action.pop(labels) if not self.opt.get(hide_labels, False): action[eval_labels] labels保留eval_labels的意义在于模型依然可以利用它计算模型侧指标如困惑度perplexity。Torch Agent 的_set_label_vec()同样识别eval_labels并将其向量化为eval_labels_vec供 loss 计算使用。此外hide_labels选项见 parlai/core/params.py 附近可进一步将评估标签完全隐藏。5.label_candidates排序/打分任务的候选答案对于支持排序ranking的任务label_candidates是一个可迭代对象存放数据集建议 Agent 可以选择的候选答案。例如 mnist-qa 任务提供如下候选见 docs/source/core/messages.mddef label_candidates(self): return [str(x) for x in range(10)] [zero, one, two, three, four, five, six, seven, eight, nine]在实际代码中DialogTeacher的act()会调用self.label_candidates()来填充该字段parlai/core/teachers.py基于 tab 分隔文本的FbDeprecatedDialogTeacher也支持通过label_candidates:a|b|c语法解析候选并会校验labels[0]是否出现在候选列表中parlai/core/teachers.py。6.text_candidates模型排序后的候选回复text_candidates是label_candidates的对偶字段收到对方给出的候选标签后模型可以选择返回一个可迭代对象其中按模型认为与对话的相关性从高到低排序的回复列表。{ text: Which number is in the image?, label_candidates: [0, 1, 2, ..., nine], text_candidates: [4, four, 0, one, ...], # 模型给出的排序 }这样教师就可以对模型的整体排序进行打分进而计算hits10、MRR等指标。7.episode_done标记一次对话的结束episode_done标志用于标记一个 episode会话/回合组的结束。ParlAI 中的对话不一定只有一个来回许多数据集包含多轮交互。单轮示例WikiMovies见 docs/source/core/messages.md{ id: wikimovies, text: what movies are about ginger rogers?, labels: [Top Hat, Kitty Foyle, The Barkleys of Broadway], episode_done: True, }多轮示例bAbI task1k:15同一个 episode 内连续多轮问答前几轮episode_doneFalse直到最后一个问题才置为True{ id: babi:task1k:15, text: Cats are afraid of sheep. Sheep are afraid of mice. Wolves are afraid of sheep. Gertrude is a cat. Winona is a cat. Emily is a sheep. Jessica is a cat. Mice are afraid of cats. What is winona afraid of?, labels: [sheep], label_candidates: [wolf, mouse, cat, sheep], episode_done: False, } { id: babi:task1k:15, text: What is jessica afraid of?, labels: [sheep], label_candidates: [wolf, mouse, cat, sheep], episode_done: False, } { id: babi:task1k:15, text: What is gertrude afraid of?, labels: [sheep], label_candidates: [wolf, mouse, cat, sheep], episode_done: False, } { id: babi:task1k:15, text: What is emily afraid of?, labels: [mouse], label_candidates: [wolf, mouse, cat, sheep], episode_done: True, }从实现看World.episode_done()parlai/core/worlds.py正是依据消息中的episode_done标志来判断对话是否结束从而决定是否进行下一轮。8.reward强化学习任务的奖励reward字段供强化学习RL任务在 observation dict 中发送奖励信号。{ text: You chose option A., reward: 1.0, }值得注意的是Message中定义了UNSAFE_FIELDS {metrics}parlai/core/message.pyjson_safe_payload()会剔除这类字段后再交付给外部客户端——这确保了诸如奖励、指标这类可能敏感的字段不会意外泄露到聊天服务等下游。9.image多模态数据VQA / Visual Dialogobservation dict 也可以包含图像。例如 VQA_v2 数据集的每个问题都关联一张图片。image字段中图像数据的格式取决于--image-mode参数的设置默认情况下图像以原始 RGB 像素返回image_mode为raw也可以先用预训练图像模型处理只把模型特征放入image字段如resnet/resnext变体甚至可以转换为文本表示以便快速调试如ascii模式。在 parlai/core/image_featurizers.py 中可以看到模式的解析逻辑self.image_mode opt.get(image_mode, no_image_model) if self.image_mode not in [no_image_model, raw, ascii]: if image_mode not in opt or image_size not in opt: raise RuntimeError(...) if resnet in self.image_mode: ... elif resnext in self.image_mode: ... else: raise RuntimeError(Image mode {} not supported.format(self.image_mode))官方文档给出的 ascii 调试示例parlai display_data --task mnist_qa --image-mode ascii其输出即为一个完整的含image字段的 observationASCII 字符画{ text: Which number is in the image?, labels: [4, four], label_candidates: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, zero, one, two, three, four, five, six, seven, eight, nine], episode_done: True, image: ... , }对应的 ASCII 转换逻辑可在_img_to_ascii()parlai/core/image_featurizers.py中找到而raw模式则直接返回 RGB 值parlai/core/image_featurizers.py。四、扩展字段Extended Fields任务自定义元数据除了上述标准字段许多数据集还会使用自定义字段来携带额外元数据。以squad:index任务为例它在消息中加入了answer_starts记录答案在文本中的起始字符下标{ id: squad, text: Architecturally, the school has a Catholic character. Atop the Main Buildings gold dome is a golden statue of the Virgin Mary. ... To whom did the Virgin Mary allegedly appear in 1858 in Lourdes France?, labels: [Saint Bernadette Soubirous], episode_done: True, answer_starts: [515], }你可以为任务添加额外字段以提供任务特定的元数据。但官方文档明确给出三点警告在特定字段上训练的模型不容易迁移到其他任务现有模型不会利用该字段在不同任务上做多任务训练会变得更难实现。为此ParlAI 默认的 SQuAD 任务并不包含answer_starts而是提供了一个具备自行查找标签索引能力的模型DrQA。这样该 Agent 也可以被训练到其他“答案在引言文本中”的任务上如部分 bAbI 任务——而这些任务并不提供answer_starts。这一设计思路体现了 ParlAI 的核心哲学用统一、通用的字段换取模型的跨任务可迁移性。五、Message 的典型使用路径从 Teacher 到 Torch Agent综合以上内容一条典型的监督学习数据流如下可用 docs/source/core/teachers.md 与 docs/source/core/torch_agent.md 进一步深入Teacher 侧FixedDialogTeacher.act()从数据中取出下一条记录构造Message若旧代码返回普通 dict会执行action Message(action)兜底转换见 parlai/core/teachers.py随后process_action()用force_set写入id并在非训练阶段把labels改名为eval_labelsparlai/core/teachers.py。World 侧World把 Teacher 的 Message 经validate()校验后传给模型 Agent 的observe()模型act()产出的 Message 再传回教师用于打分。模型侧TorchAgent.observe()把 Message 中的text/labels/eval_labels向量化为text_vec/labels_vec/eval_labels_vec等派生字段并用force_set安全写入parlai/core/torch_agent.py。正是因为两端都遵循同一套标准字段约定一个模型才能在不同任务间自由迁移教师只要产出符合规范的 Message模型侧无需改动即可训练。六、小结与最佳实践字段类型用途备注textstr发送的文本内容最标准字段respond()强制要求idstr发送者自标识通常为任务名labelsiterable监督训练目标训练阶段使用eval_labelsiterable验证/测试目标由labels自动迁移而来防泄漏label_candidatesiterable数据集建议的候选答案用于排序任务text_candidatesiterable模型排序后的候选回复用于计算hits10、MRRepisode_donebool标记 episode 结束决定World.episode_done()rewardfloatRL 奖励信号强化学习任务使用image多变图像数据/特征/ASCII由--image-mode决定格式自定义字段任意任务特定元数据慎用影响模型可迁移性总结几条核心实践建议遵循标准字段尽量只使用text、labels、label_candidates、episode_done等标准字段这是模型跨任务迁移和多任务训练的前提。不要直接覆盖字段Message 的写保护是刻意设计确需更新时显式调用force_set()否则将触发RuntimeError。区分训练与评估让框架自动完成labels→eval_labels的迁移不要自己在 Teacher 中混用也不要在评估数据上训练。慎用扩展字段自定义元数据如answer_starts只应在必要时添加并清楚其带来的可迁移性代价优先考虑让模型自行推断。多模态任务正确配置--image-mode调试用ascii训练用raw或预训练特征模式具体取值范围参考 parlai/core/image_featurizers.py。掌握 Message 的字段契约与底层保护机制你就掌握了 ParlAI 中 Agent 通信的“通用语言”——无论编写新任务、调试数据流还是训练多任务模型这都将是贯穿始终的基础能力。赞分享NLP人工智能深度学习【免费下载链接】ParlAIA framework for training and evaluating AI models on a variety of openly available dialogue datasets.项目地址https://gitcode.com/gh_mirrors/pa/ParlAI点击查看免费下载相关推荐ParlAI Agent 架构全解parlai.core.agents 核心类、消息循环与加载机制ParlAI Agent 架构全解parlai.core.agents 核心类、消息循环与加载机制 导读 本文聚焦 ParlAI 框架中最核心的模块之一——NLP人工智能深度学习Browser Use 的 Message Manager 深度解析Agent 与 LLM 之间对话秘书的工作机制Browser Use 的 Message Manager 深度解析Agent 与 LLM 之间对话秘书的工作机制 本教程对应 docs/Browser Us人工智能AI 应用AI Agent一条指令上岗AI 代理的全自动交易路径一条指令上岗AI 代理的全自动交易路径 人类交易员有券商 AppAI 代理却长期寄人篱下。 AI Trader 是专为 Claude Code、Open后端前端金融科技AI AgentAI 技能上一篇OpCore Simplify3分钟完成黑苹果EFI配置的终极解决方案下一篇100-exercises-to-learn-rust 快速上手新手最省心的 Rust 练习环境与 IDE 配置指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考