标签: AGI

  • ChatGLM:从 GLM-130B 到 GLM-4,一个不断进化的语言模型家族

    ChatGPT 的横空出世,其强大的能力最初得益于 2022 年 11 月发布的 GPT-3.5 模型 [25],并在 2023 年 3 月升级到 GPT-4 [27]。OpenAI 表示,GPT-3.5 系列在 GPT-3 的基础上,通过指令微调、监督微调 (SFT) 和/或来自人类反馈的强化学习 (RLHF) [28] 进行了改进。2020 年发布的 GPT-3 [3] 在参数规模上实现了巨大飞跃,从 GPT-1 的 1.17 亿个参数和 GPT-2 的 15 亿个参数,提升至 1750 亿个参数。这种规模的提升使 GPT-3 具备了上下文学习和泛化能力,也推动了大型语言模型 (LLMs) 的兴起 [6; 41]。

    受 GPT-3 的启发,我们提出了通用语言模型 (GLM) 架构 [11],并于 2021 年开源了 GLM-10B 模型(参见图 1 中的 GLM 时间线)。从 2021 年底开始,我们开始预训练 GLM-130B [54]。目标是训练一个 1000 亿规模的模型,以匹配或超越 GPT-3(davinci),同时验证在这一规模上成功训练模型的技术,以及其他努力,如 OPT-175B [55] 和 BLOOM-176B [32]。我们于 2022 年 7 月完成了 GLM-130B 的 4000 亿个 token 的训练和评估,并在 8 月发布了模型和预训练细节 [54]。根据 2022 年 11 月的 HELM 数据,GLM-130B 在各个维度上都与 GPT-3(davinci)相当 [19]。

    在此之后,我们开始对 GLM-130B 进行指令微调。后来,ChatGPT 进一步促使我们使用 SFT 和 RLHF 对基础模型进行对齐。我们从头开始创建和整理了提示-响应对,并执行了 SFT,同时开始研究如何有效地应用 RLHF。2023 年 3 月 14 日,对齐后的模型 ChatGLM-130B 在 https://chatglm.cn 上上线。此外,我们还在同一天开源了更小版本的 ChatGLM-6B [13],它吸引了比预期多得多的关注。它的设计参数为 62 亿,旨在:1)促进预训练和后训练技术以及数据选择的快速迭代;2)使用 INT4 量化在消费级显卡上进行本地部署。从那时起,我们一直在快速探索和改进我们的预训练和对齐技术,每隔三个月就会发布第二代和第三代 ChatGLM 系列,这两代模型都是从头开始预训练的。

    ChatGLM-6B 在大约一万亿个中英文语料库上进行预训练,上下文长度为 2048(2K),主要通过 SFT 进行补充。ChatGLM2-6B 于 6 月发布,在更多更好的数据上进行预训练和对齐,与前一代相比有了显著改进,包括 MMLU 提高了 23%,GSM8K 提高了 571%,BBH 提高了 60%。通过采用 FlashAttention 技术 [8],其上下文长度扩展到 32K。此外,多查询注意力 (Multi-Query Attention) [34] 的整合使推理速度提高了 42%。更进一步,我们开发了第二代代码模型 CodeGeeX2-6B,它在另外 6000 亿个代码 token 上进行预训练。它在 HumanEval-X 的衡量下,展示了与第一代模型 CodeGeeX-13B [58] 相比,Pass@1 有所提高,在 Python 上提高了 57%,在 C++ 上提高了 71%,在 Java 上提高了 54%,在 JavaScript 上提高了 83%,在 Go 上提高了 56%。通过进一步实现更多样化的训练数据集、更充足的训练步骤和更优化的训练策略,ChatGLM3-6B 在语义、数学、推理、代码和知识方面超过了 42 个基准。从这一代开始,ChatGLM 还支持函数调用和代码解释器,以及复杂的任务 [9; 36; 51]。在这些开发过程中,我们还开发了参数规模为 15 亿、30 亿、120 亿、320 亿、660 亿和 1300 亿的模型,使我们能够验证我们的观察结果并建立我们自己的扩展定律。

    吸取了所有经验教训,我们开始了 GLM-4 的训练。第一个截止检查点随后经历了多阶段的后训练过程(例如,SFT、RLHF、安全对齐),目前重点关注中英文。随后,它被开发成两个不同的版本:GLM-4 和 GLM-4 All Tools,两者都支持 128K 的上下文长度。从 2024 年 1 月 16 日起,GLM-4(0116)已通过 GLM-4 API 在 https://bigmodel.cn 上提供,GLM-4 All Tools 可通过网站 https://chatglm.cn 和支持创建自己的代理(GLMs)的移动应用程序访问。最新的模型是 GLM-4(0520)和 GLM-4-Air(0605),它们在预训练和对齐方面都有所升级。GLM-4-Air 在保持与 GLM-4(0116)相当的性能的同时,降低了延迟和推理成本。GLM-4 的评估是在各种语言基准上进行的。这些评估评估了 GLM-4 在英语中的通用能力、英语和中文的指令遵循能力、以及中文的对齐、长上下文和代理能力。

    首先,在最常用的英语学术基准上,包括 MMLU、GSM8K、MATH、BBH、GPQA 和 HumanEval,GLM-4 0520 的性能与 GPT-4 0613 [27] 和 Gemini 1.5 Pro [40] 相当。例如,它在 MMLU 上的得分分别为 83.3、86.4 和 83.7。其次,根据 IFEval [61],GLM-4 在提示和指令级别上的指令遵循能力与 GPT-4-Turbo 在英语和中文中的能力相当。第三,在中文语言对齐方面,GLM-4 在 AlignBench [21] 的八个维度上都超越了 GPT-4,并与 GPT-4-Turbo 相匹配。最后,在长上下文任务中,GLM-4(128K)模型的性能与 GPT-4 Turbo 和 Claude 3 Opus 相匹配,如 LongBench-Chat [1] 所测,分别为 87.3、87.2 和 87.7。

    GLM-4 All Tools 模型专门针对更好地理解用户意图和自主选择最合适的工具来完成任务进行了对齐。例如,它可以以多轮方式通过网页浏览器访问在线信息,使用 Python 解释器解决数学问题,利用文本到图像模型生成图像,以及调用用户定义的函数。图 2 展示了 GLM-4 All Tools 使用网页浏览器和 Python 解释器来解决用户查询“搜索 2000 年至 2023 年的全球人口,然后计算年平均增长率”的示例。我们的第一手测试表明,它不仅与 GPT-4 All Tools 的能力相匹配,而且在常见任务中往往超过了它。

    继我们三代开源 ChatGLM-6B 模型之后,我们还开源了 GLM-4-9B(128K 和 1M 上下文长度)模型。GLM-4-9B 在大约一万亿个多语言语料库上进行预训练,上下文长度为 8192(8K),并使用与 GLM-4(0520)相同的管道和数据进行后训练。在训练计算量较少的情况下,它超越了 Llama-3-8B [24],并支持 GLM-4 中所有工具的功能。我们还提供了一个实验模型 GLM-4-9B-Chat-1M,其上下文长度为 100 万(1M)(约 200 万个汉字)。表 1 展示了三代 ChatGLM-6B 模型和 GLM-4-9B 的性能,说明了 ChatGLM 随着时间的推移而不断改进。

    图 3 总结了从 GLM-130B 到 GLM-4 All Tools 的主要改进和功能。在这段旅程中,我们还为代码 LLMs(CodeGeeX [58])以及用于图像理解的视觉语言模型(CogVLM [45] 和 CogAgent [16])和文本到图像生成(CogView [10; 59])的开源开发做出了贡献。开源模型和数据可以通过 https://github.com/THUDMhttps://huggingface.co/THUDM 访问。

    ChatGLM 技术

    在本节中,我们将介绍我们在 ChatGLM 中采用和开发的预训练和后训练技术,包括模型架构、预训练数据、对齐和 All Tools。我们已经发布了详细的技术报告,介绍了我们用来达到 GLM-4 的每项主要技术的细节。

    预训练数据

    我们的预训练语料库由来自不同来源的多语言(主要是英语和中文)文档组成,包括网页、维基百科、书籍、代码和论文。数据处理流程主要包括三个阶段:去重、过滤和分词。去重阶段通过去除重复或相似的文档来提高数据多样性,包括精确去重和模糊去重。过滤阶段通过去除包含攻击性语言、占位符文本、源代码等噪音文档来提高数据质量。分词阶段将文本转换为一系列 token,以便进行进一步处理。预训练数据中的 token 数量直接影响模型训练速度。为了优化这方面,我们采用字节级字节对编码 (BPE) 算法 [33],分别学习中文和多语言 token,并将它们与 tiktoken [26] 中 cl100k_base tokenizer 的 token 合并成一个统一的词汇表,大小为 150,000。在最终的训练集中,我们重新调整了不同来源的权重,以提高书籍和维基百科等高质量和教育性来源的比例。为此,预训练语料库包含大约一万亿个 token。

    在 ChatGLM 开发的四代过程中,我们的发现与现有研究结果一致 [60]:数据质量和多样性对于构建有效的 LLMs 至关重要。尽管我们从经验教训中获得了经验和见解,但迄今为止,我们还没有找到可以指导数据收集、清理和选择过程的基本原则。

    架构

    GLM 家族的 LLMs 是基于 Transformer [43] 构建的。在 GLM-130B [54] 中,我们探索了各种选项来稳定其预训练,同时考虑了我们当时面临的硬件限制。具体来说,GLM-130B 利用 DeepNorm [44] 作为层归一化策略,并使用旋转位置编码 (RoPE) [38] 以及带有 GeLU [15] 激活函数的门控线性单元 (GLU) [35] 在 FFNs 中。在我们的探索过程中,我们研究了不同的策略来提高模型性能和推理效率。最新的 GLM-4 模型采用以下架构设计选择。

    • 除了 QKV 之外没有偏差: 为了提高训练速度,我们去除了所有偏差项,除了注意力层的 Query、Key 和 Value (QKV) 中的偏差。这样做,我们观察到长度外推略有改善。
    • RMSNorm 和 SwiGLU: 我们采用 RMSNorm 和 SwiGLU 分别替换 LayerNorm 和 ReLU。这两个策略被观察到具有更好的模型性能。
    • 旋转位置嵌入 (RoPE): 我们将 RoPE 扩展到二维形式,以适应 GLM 中的二维位置编码。
    • 分组查询注意力 (GQA): 我们用分组查询注意力 (GQA) 替换多头注意力 (MHA),以减少推理过程中的 KV 缓存大小。由于 GQA 使用的参数少于 MHA,因此我们增加了 FFN 参数数量,以保持相同的模型大小,即设置 dffn 为隐藏大小的 10/3。

    我们模型的上下文长度从 2K(ChatGLM)扩展到 32K(ChatGLM2 和 ChatGLM3),以及 128K 和 1M(GLM-4)。这种扩展不仅通过上下文扩展(位置编码扩展 [30; 5] 和长文本的持续训练 [47])实现,而且通过长上下文对齐实现,使 GLM-4 能够有效地处理长上下文(参见 [1] 获取技术细节)。

    对齐

    预训练为 LLMs 打下了基础,而后训练 [28] 进一步细化了这些模型,使其与人类的偏好相一致,例如理解人类意图、遵循指令和促进多轮对话。对于 GLM-4,对齐主要通过监督微调 (SFT) 和来自人类反馈的强化学习 (RLHF) [17] 实现。在 SFT 中,我们发现真实的人类提示和交互,而不是基于模板或模型生成的响应,对于对齐质量至关重要。虽然 SFT 在很大程度上使基础模型与人类的偏好相一致,但 RLHF 可以进一步帮助缓解响应拒绝、安全、生成双语 token 的混合以及多轮一致性等问题。

    对于第一代模型(ChatGLM-6B 和 ChatGLM-130B),提示-响应对主要由模型开发者标注。对于后来的模型,对齐数据是内部标注数据和从第三方获得的专有数据的组合,并经过相对严格的质量控制措施。与现有做法类似 [42],标注者被指示从多个维度对模型响应进行评分,包括安全性、真实性、相关性、帮助性和人类偏好。

    ChatGLM 技术

    在 ChatGLM 的开发过程中,我们已经引入了并将在未来发布用于增强其性能的技术。

    • LLMs 的涌现能力 [12]: 我们研究了预训练损失与下游任务性能之间的关系,发现对于相同的预训练损失,不同模型大小和训练 token 的 LLMs 会产生相同的下游性能。我们还发现,在某些任务(例如 MMLU 和 GSM8K)上,只有当预训练损失低于某个阈值时,性能才会超过随机机会。因此,我们将涌现能力重新定义为那些由预训练损失较低的模型表现出的能力 [12]。
    • LongAlign [1]: 为了扩展 LLMs 的上下文窗口大小,我们提出了 LongAlign——一个用于长上下文对齐的综合方案。它使 GLM-4 能够处理长上下文文本(最多 128K 个 token),其性能与 Claude 2 和 GPT-4 Turbo(1106)相当。
    • ChatGLM-Math [48]: 为了改进 LLMs 中的数学问题求解,我们引入了 ChatGLM-Math,它利用自我批评而不是外部模型或手动标注来进行数据选择。
    • ChatGLM-RLHF [17]: 为了使 LLMs 与人类反馈相一致,我们引入了 ChatGLM-RLHF——我们在 LLMs 中应用 PPO 和 DPO 的实践。
    • 自对比 [22]: 为了避免对昂贵的人类偏好反馈数据的需求,我们开发了一种无反馈对齐策略——自对比。它利用目标 LLM 本身来为其 RLHF 对齐自生成大量负样本。
    • AgentTuning [53]: 为了提高 LLMs 的代理能力,我们开发了 AgentTurning 框架,以及包含代理与环境之间高质量交互轨迹的 AgentInstruct 指令微调数据集。
    • APAR [20]: 为了提高 LLMs 对具有层次结构的响应的推理速度,我们提出了一种自动并行自动回归 (APAR) 生成方法。它利用指令微调来训练 LLMs 计划其(并行)生成过程并执行 APAR 生成。
    • 基准: 我们还开发了几个开放的 LLM 基准,包括用于评估 LLMs 作为代理的 AgentBench [23]、用于评估 LLMs 的长上下文处理性能的 LongBench [2]、用于衡量 ChatGLM 与中文内容对齐质量的 AlignBench [1]、用于评估 HumanEval [4] 问题在 Python 以外的编程语言中的 HumanEval-X [58],以及用于衡量模型解决实际编程任务能力的 NaturalCodeBench (NCB)。

    GLM-4 All Tools

    最新的 ChatGLM 模型是 GLM-4 和 GLM-4 All Tools,它们都使用上述技术进行训练和对齐。GLM-4 All Tools 是一个进一步对齐以支持智能代理和相关任务的模型版本。它可以自主理解用户意图,规划复杂的指令,并调用一个或多个工具(例如,网页浏览器、Python 解释器和文本到图像模型)来完成复杂的任务。图 4 展示了 GLM-4 All Tools 系统的整体流程。当用户发出一个复杂的请求时,模型会分析任务并逐步规划解决过程。如果它确定无法独立完成任务,它将依次调用一个或多个外部工具,利用它们的中间反馈和结果来帮助解决任务。

    基于 GLM-4 的所有工具功能,我们还开发了 GLMs 应用程序平台,允许用户为特定任务创建和自定义自己的代理。GLMs 不仅支持嵌入式 Python 解释器、网页浏览器、文本到图像模型,还支持用户定义的函数、API 和外部知识库,以更有效地满足用户需求。

    GLM-4 能力

    我们从多个角度考察 GLM-4 模型的能力,包括在学术基准上的基础能力、代码问题解决能力、英语环境中的代理能力、以及指令遵循能力、中英文的长上下文能力,以及中文的对齐能力。如前所述,GLM-4 主要在中英文上进行预训练,并主要对齐到中文。在本节中,我们主要报告最新 GLM-4 版本(即 GLM-4(0520)和 GLM-4-Air(0605))的结果,因为 GLM-4(0520)在评估的基准上略好于其原始的 0116 版本。在评估期间,GLM-4 和 GLM-4-Air 都以 BFloat16 精度进行部署。

    对于基线,我们展示了 GPT-4(0603)、GPT-4 Turbo(1106,2024-04-09)、Claude 2、Claude 3 Opus 和 Gemini 1.5 Pro 的结果,所有这些结果都是从相应的技术报告中提取或通过其公共 API 进行测试的。

    总的来说,GLM-4 在标准基准、指令遵循、长上下文、代码问题解决和英语环境中的代理能力方面,与最先进的模型(GPT-4-Turbo、Gemini 1.5 Pro 和 Claude 3 Opus)相近。在中文对齐方面,它在各个领域(如基础语言能力、高级中文理解、专业知识和开放式问题)上都表现出强大的性能,与 SOTA 模型相比。总之,GLM-4 在中文语言任务方面处于领先地位。它还展示了与 GPT-4 和 Claude 3 Opus 在中文数学和逻辑推理能力方面相当的性能,尽管它落后于 GPT-4 Turbo。

    3.1 学术基准评估

    为了评估基础模型的总体性能,我们选择了六个常用的基准,涵盖知识、数学、推理、常识和编码:

    • MMLU [14]: 从各种考试中收集的多项选择题,包括数学、历史、计算机科学等等。我们将所有答案提供给模型,并要求它选择答案的字母。
    • GSM8K [7]: 8500 道小学数学应用题(测试集中有 1000 道),要求模型使用数学概念解决现实生活中的情境问题。我们为此基准使用链式思维提示 [46]。
    • MATH: 12500 道具有挑战性的竞赛级数学题(测试集中有 5000 道)。我们为此基准使用链式思维提示 [46]。
    • BBH [39]: 一套 23 个具有挑战性的 BIG-Bench [37] 任务。我们为此基准使用链式思维提示 [46]。
    • GPQA [31]: 生物学、化学和物理学中的研究生级多项选择基准。
    • HumanEval [4]: 一个编码基准,通过自动测试用例检查来衡量合成函数的正确性。

    我们将 GLM-4 的性能与原始 GPT-4 [27] 进行比较。结果如表 2 所示。我们可以观察到,GLM-4 在 MMLU 上的准确率达到了 GPT-4 的 96.3%,并在其他基准上超过了 GPT-4。总的来说,GLM-4 的基础能力接近 GPT-4-Turbo 和 Claude 3 Opus。

    3.2 指令遵循评估

    我们使用最近引入的 IFEval 数据集 [61] 来评估 GLM-4 在遵循指令方面的熟练程度。该数据集包含 541 个提示,这些提示源于 25 个不同的指令,这些指令可以通过明确的标准进行验证(例如,“以以下内容结束你的电子邮件:P.S. 我很喜欢蛋糕”可以通过字符串匹配进行验证)。我们遵循 [61] 中概述的方法,以严格模式和宽松模式计算提示级别和指令级别的准确率。为了进一步评估模型在遵循中文指令方面的性能,我们将原始提示翻译成中文,省略了不适用于中文的指令(如大写字母),并调整评分脚本以适应中文数据。

    3.3 对齐评估

    AlignBench [21] 提供了一种自动的 LLMs-as-Judge 方法,用于对齐中文上下文中的 LLMs。它包含 683 个查询,涵盖 8 个不同的类别,并使用基于 GPT-4 的多维规则校准点式参考评分方法来判断模型响应。我们对 AlignBench-v1.1 进行评估,它更仔细地改进了参考生成质量,特别是通过将从网页收集的人工证据与知识要求问题的 URL 补充,这些问题占总查询的 66.5%。在这个版本上,几乎所有 LLMs 的得分都比之前在 AlignBench 上的得分低。

    3.4 长上下文处理能力评估

    为了获得 GLM-4 在长文本任务上的性能,我们在 LongBench-Chat [1] 上进行了评估,这是一个上下文长度从 10-100k 不等的基准集,涵盖了用户经常使用的大量长文本场景,例如文档问答、摘要和编码。为了更详细地比较 GLM-4 在不同语言上的性能,我们还根据语言对 LongBench-Chat 进行划分。这产生了两个不同的部分:中文和英文。我们分别提供了这两个部分的结果,提供了对 GLM-4 跨语言能力的细致概述。

    关于具体的评估设置,我们根据 GPT-4 对每个模型的输出进行评分,在 LongBench-Chat 中采用少样本策略。此外,为了最大程度地减少得分差异并得出更可靠的统计结论,我们进行了重复评估。随后,我们计算这些多次评估的平均值,以确保最终的性能指标反映了对 GLM-4 在不同条件下的行为的全面了解。

    表 5 展示了我们实验中获得的结果。可以清楚地观察到,GLM-4 在英语提示上的性能与 GPT-4 Turbo 和 Claude 3 Opus 相一致,并且它在中文提示上可以超过它们中的最佳者。

    3.5 在现实世界用户提示上的编码评估

    虽然 HumanEval [4] 已被广泛用于评估代码生成,但其大多数问题都可以归类为入门级算法。然而,在实践中,真实用户会提出用于生产目的的复杂问题,这些问题通常远远超出了 HumanEval 的范围。此外,之前的工作报道了 HumanEval 污染了训练数据 [27; 18; 50],无论是它们自己的 LLM 还是其他 LLM,这使得 HumanEval 上的结果比以前不太可信。

    因此,除了 HumanEval 之外,我们还在 NaturalCodeBench (NCB) [56] 上评估了 GLM-4,这是一个具有挑战性的双语编码基准,它源于自然用户提示,以反映现实世界编码任务的复杂性。结果如表 6 所示。它表明,GLM-4 在实际场景中的编码性能与 Claude 3 Opus 相近。虽然与 GPT-4 模型相比仍存在差距,但考虑到 GLM-4 的双语平衡性质,通过在接下来的迭代中采用更好的训练策略和数据整理,它在 NCB 上的性能还有很大的提升空间。

    3.6 函数调用评估

    为了评估 GLM 模型在函数调用方面的性能,我们在 Berkeley 函数调用排行榜 [49] 上进行了评估,这是一个包含 2k 个问题-函数-答案对的基准。该基准评估模型在调用函数方面的能力,分为三个类别:通过抽象语法树 (AST) 进行评估、通过执行 API 进行评估和相关性检测。第一类将模型输出的函数与函数文档和可能的答案进行比较,并进行 AST 分析。第二类通过执行生成的函数调用来检查响应的正确性。相关性检测评估模型识别不适合回答用户问题的函数的能力。结果如表 7 所示。我们可以观察到,GLM-4(0520)的函数调用能力与 GPT-4 Turbo(2024-04-09)相当,而 GLM-4-9B-Chat 显著超过 Llama-3-8B-Instruct。另一个观察结果是,总体准确率没有随着模型大小的增加而提高,而 GLM-4-9B-Chat 甚至可以超过 GLM-4-Air。另一方面,我们观察到,执行摘要的性能(评估现实世界 API 的执行结果)随着模型大小的增加而平稳提高。

    3.7 代理能力评估

    人们普遍观察到,LLMs 能够在各种环境和上下文中充当智能代理 [29; 52],被称为 LLMs-as-Agents [23]。因此,我们使用 AgentBench [23] 对 GLM-4 以及其他比较 LLMs 进行了评估,这是一个全面的代理基准,用于评估各种实际环境中的文本型 LLMs,包括基于代码、基于游戏和基于网络的上下文。具体来说,我们对 8 个 AgentBench 环境中的 7 个进行了评估,除了数字卡牌游戏,因为它需要更长的时间与之交互。总分是使用 AgentBench [23] 中提供的原始每个数据集权重计算的。

    3.8 All Tools 评估

    GLM-4 进一步对齐以支持智能代理和用户在 https://chatglm.cn 上自配置的 GLMs 功能,由此产生的模型是 GLM-4 All Tools。如前所述,GLM-4 All Tools 可以通过自主理解用户意图、规划逐步指令以及调用多个工具(包括网页浏览器、Python 解释器和文本到图像模型(例如,CogView3 [59]))来完成复杂的任务。表 9 显示,GLM-4 All Tools(Web)在 Python 解释器上用于解决数学问题、浏览器上用于信息搜索方面,与 ChatGPT-4(Web)的性能相当。

    4 安全和风险

    我们致力于确保 GLM-4 作为一个安全、负责任和无偏见的模型运行。除了解决常见的伦理和公平问题外,我们还仔细评估并减轻模型在现实世界场景中可能对用户造成的潜在危害。

    风险缓解

    我们在预训练阶段仔细清理数据,通过删除包含敏感关键词的文本和来自预定义黑名单的网页。在对齐阶段,我们评估每个训练样本的安全性,并删除任何可能造成潜在风险的样本。在比较多个模型输出时,无害性也是偏好对齐的重要标准。

    我们有一个红队,他们不断用棘手的问题挑战模型,这些问题往往会导致不安全的答案。我们收集了来自 GLM-4 的所有有害问题-答案对,并使用人工标注对其进行改进,以进一步进行模型对齐。

    安全评估

    我们在 SafetyBench [57] 数据集上评估了 GLM-4 模型,该数据集从 7 个维度评估每个模型的能力:伦理和道德(不道德行为)、非法活动(对法律的基本了解)、心理健康(对心理健康的不利影响)、攻击性(攻击性行为)、身体健康(可能造成身体伤害的危险行为)、隐私和财产(隐私泄露或财产损失)、不公平性和偏见。我们对 SafetyBench 的中文子集评估了不同的模型,该子集是通过删除可能被屏蔽的敏感性很高的问题创建的,以减轻不同 API 安全策略的干扰。

    表 10 显示了 GLM-4 和 SOTA 模型的安全结果。在大多数维度上,GLM-4(0520)表现出具有竞争力的安全性能,总体上它与 Claude 3 Opus 实现了相当的性能。GLM-4 在身体健康维度上略微落后于 GPT-4 家族的模型,这需要关于物理世界的强大常识知识,以避免潜在风险。我们已经投入了更多努力,朝着这个方向发展一个更强大和更安全的 GLM 模型。

    5 结论

    在本报告中,我们介绍了从 GLM-130B 到 GLM-4(All Tools)的 ChatGLM 大型语言模型家族。在过去一年半的时间里,我们从第一手经验中在理解大型语言模型的各个方面取得了巨大进展。随着每一代模型的开发,团队已经学习并应用了更有效、更高效的模型预训练和对齐策略。最新的 ChatGLM 模型——GLM-4(0116、0520)、GLM-4-Air(0605)和 GLM-4 All Tools——在理解和执行复杂任务方面取得了显著进步,通过自主使用外部工具和函数来实现。这些 GLM-4 模型在性能上与最先进的模型(如 GPT-4 Turbo、Claude 3 Opus 和 Gemini 1.5 Pro)相当,在某些情况下甚至超过了它们,特别是在处理与中文相关的任务时。此外,我们致力于通过开源模型权重和在这段旅程中开发的技术来促进 LLMs 的可访问性和安全性。我们的开源模型,包括语言、代码和视觉模型,仅在 2023 年就吸引了超过 1000 万次下载。目前,我们正在使用迄今为止学到的所有知识来开发更强大的模型。未来,我们将继续通过开源来普及尖端的 LLM 技术,并将模型能力的边界推向让机器像人类一样思考的目标。

    致谢

    我们要感谢所有数据标注者、基础设施运营人员、合作者和合作伙伴,以及 Zhipu AI 和清华大学未在报告中明确提及的所有为 ChatGLM 提供支持、反馈和贡献的人员。我们还要感谢 Zhipu AI 的张宇轩和贾伟,以及 Hugging Face、ModelScope、WiseModel 等团队在 GLM 家族模型的开源工作中提供的帮助。

    参考文献

    [1] LongAlign: A Comprehensive Recipe for Long Context Alignment. https://arxiv.org/abs/2404.05640

    [2] LongBench: A Benchmark for Evaluating Long Context Handling Abilities of LLMs.


    Q: 这篇论文试图解决什么问题?

    A: 这篇论文介绍了ChatGLM,这是一个不断发展的大型语言模型家族,包括从GLM-130B到GLM-4的各个版本。论文的主要目标是展示这个家族中最新的GLM-4系列模型,包括GLM-4、GLM-4-Air和GLM-4-9B,这些模型利用了之前三代ChatGLM的经验教训和洞察力进行训练。这些模型主要针对中文和英文使用进行了高质量的对齐,通过多阶段的后训练过程实现,包括监督式微调和从人类反馈中学习。

    论文试图解决的问题包括:

    1. 大型语言模型的持续改进:通过不断的技术迭代和训练方法的优化,提高模型的性能。
    2. 多语言支持:尽管主要关注中文和英文,但模型也支持其他语言,以满足不同用户的需求。
    3. 对齐人类意图:通过后训练过程,提高模型理解用户意图和执行指令的能力。
    4. 长文本处理:通过扩展模型的上下文长度,提升模型处理长文本的能力。
    5. 实用功能集成:GLM-4 All Tools模型能够理解用户意图并自主决定何时以及使用哪些工具来有效完成任务,如网页浏览器、Python解释器、文本到图像模型和用户定义的函数。

    总的来说,论文的目标是展示ChatGLM家族在大型语言模型领域的最新进展,并证明其在多种任务和能力上与当前最先进模型的竞争力。

    Q: 有哪些相关研究?

    A: 论文中提到了多个与大型语言模型(LLMs)相关的研究工作,以下是一些主要的相关研究:

    1. GPT-3系列:由OpenAI开发,包括GPT-3.5和GPT-4,这些模型通过引入指令调整、监督式微调(SFT)和/或从人类反馈中学习的强化学习(RLHF)来改进性能。
    2. OPT175B 和 BLOOM-176B:这些是其他研究团队开发的大规模模型,与GLM-130B一样,旨在探索和验证在大规模数据集上训练模型的技术。
    3. Transformer架构:这是许多现代语言模型的基础,包括GLM系列。它引入了自注意力机制来处理串行数据。
    4. FlashAttention:一种提高注意力机制效率的技术,由Dao et al. (2022) 提出。
    5. CodeGeeX:一个专注于代码生成的预训练模型,由Zheng et al. (2023) 开发。
    6. CogVLM 和 CogAgent:这些是视觉语言模型,分别用于图像理解和基于GUI的代理任务。
    7. CogView:一个文本到图像的生成模型,由Ding et al. (2021) 提出。
    8. MMLU:一个多语言、多任务的语言理解评估基准,由Hendrycks et al. (2021) 开发。
    9. GSM8KMATHBBHGPQA 和 HumanEval:这些是用于评估模型在特定领域(如数学问题解答、编程等)性能的基准测试。
    10. AlignBench:一个评估模型在中文上下文中对齐能力的基准测试,由Liu et al. (2023) 提出。
    11. LongBench:一个评估模型处理长文本能力的基准测试,由Bai et al. (2023) 开发。
    12. AgentBench:一个评估模型作为智能代理在各种环境中的表现的基准测试,由Liu et al. (2023) 提出。

    这些研究为GLM系列模型的开发提供了技术背景和评估标准,同时也展示了大型语言模型领域的最新进展。

    Q: 论文如何解决这个问题?

    A: 论文通过以下方法解决大型语言模型的开发和优化问题:

    1. 多代模型开发:从GLM-130B到GLM-4,每一代模型都在前一代的基础上进行改进,利用之前的经验教训和洞察力。
    2. 预训练和后训练技术:使用高质量的数据集进行预训练,并采用多阶段后训练过程,包括监督式微调(SFT)和从人类反馈中学习的强化学习(RLHF),以提高模型与人类意图的对齐。
    3. 模型架构优化:在GLM-4中采用了无偏置(除Query、Key、Value外)、RMSNorm、SwiGLU、二维Rotary Positional Embedding(RoPE)和Group Query Attention(GQA)等技术来提升模型性能和推理效率。
    4. 上下文长度扩展:通过持续训练和长上下文对齐技术,如LongAlign,扩展模型的上下文长度,使GLM-4能够有效处理长文本。
    5. 智能工具集成:GLM-4 All Tools模型能够理解用户意图,并自主选择使用适当的工具(如Web浏览器、Python解释器、文本到图像模型等)来完成任务。
    6. 性能评估:在多种语言基准上评估GLM-4的性能,包括学术基准、指令跟随、长文本处理、编程问题解决和代理能力。
    7. 安全性和风险评估:通过数据清洗、安全评估和风险缓解策略,确保GLM-4作为安全、负责任和无偏见的模型运行。
    8. 开放模型和数据:通过开源模型权重、技术和数据,促进大型语言模型技术的普及和安全。
    9. 持续迭代和改进:基于当前的模型和技术,继续开发更强大的模型,以推动机器模拟人类思维的边界。

    通过这些方法,论文展示了ChatGLM家族在大型语言模型领域的进步,并证明了其在多种任务上与现有最先进模型的竞争力。

    Q: 论文做了哪些实验?

    A: 论文中进行了一系列实验来评估GLM-4模型的性能,包括以下几个方面:

    1. 学术基准测试:使用MMLU、GSM8K、MATH、BBH、GPQA和HumanEval等标准学术基准来评估模型的一般性能。
    2. 指令跟随能力评估:使用IFEval数据集来评估GLM-4在遵循指令方面的能力,包括在英语和中文环境中的表现。
    3. 中文对齐评估:使用AlignBench来评估GLM-4在中文上下文中的对齐能力,包括数学逻辑、语言理解和专业知识等多个维度。
    4. 长文本处理能力评估:使用LongBench-Chat来评估GLM-4处理长文本的能力,包括中文和英文的长文本场景。
    5. 实际编程问题解决:使用NaturalCodeBench来评估GLM-4在实际编程问题上的表现,包括Python和Java两种编程语言。
    6. 函数调用能力评估:使用Berkeley Function Call Leaderboard来评估GLM-4在函数调用方面的能力。
    7. 代理能力评估:使用AgentBench来评估GLM-4作为智能代理在多种环境中的表现,包括基于代码、游戏和网络的环境。
    8. 安全性评估:使用SafetyBench来评估GLM-4在安全性方面的性能,包括伦理道德、非法活动、心理健康等多个维度。
    9. GLM-4 All Tools功能评估:评估GLM-4 All Tools模型在集成多种工具(如Web浏览器、Python解释器和文本到图像模型)后完成复杂任务的能力。

    这些实验结果表明GLM-4在多个方面与现有的最先进模型(如GPT-4 Turbo、Claude 3 Opus和Gemini 1.5 Pro)具有竞争力,特别是在处理与中文相关的任务时。此外,实验还揭示了GLM-4在某些领域(如代码相关问题解决)中存在的改进空间。

    Q: 有什么可以进一步探索的点?

    A: 尽管论文中已经展示了许多关于GLM-4模型的实验和评估,但仍有一些领域可以进一步探索:

    1. 模型泛化能力:研究GLM-4在未见过的数据或领域上的表现,特别是在低资源语言或特定行业术语上。
    2. 模型解释性:提高模型的可解释性,帮助用户理解其决策过程,特别是在复杂任务或推理任务中。
    3. 多模态能力:虽然当前模型主要关注文本,但可以探索将视觉、音频等多模态数据集成到模型中。
    4. 鲁棒性和错误分析:深入分析模型在特定任务或数据集上失败的原因,以改进模型的鲁棒性。
    5. 交互式学习:研究模型如何在与用户的交互中学习并改进其性能,特别是在开放式对话系统中。
    6. 安全性和隐私保护:进一步研究如何保护用户的隐私并确保模型的输出不会引起安全问题。
    7. 模型压缩和加速:探索模型压缩技术,以减少模型的大小和提高推理速度,使其更适合在资源受限的环境中使用。
    8. 跨语言能力:研究模型在处理跨语言问题时的能力,例如代码中的自然语言注释或多语言文档的翻译和理解。
    9. 长期记忆和上下文保持:研究如何改进模型在长时间对话或复杂任务中保持上下文信息的能力。
    10. 可扩展性:探索如何将模型扩展到更大的规模,以及这种扩展如何影响其性能和效率。
    11. 公平性和偏见减少:持续监测和减少模型可能表现出的偏见,确保其对所有用户都是公平的。
    12. 实际应用场景:将模型应用于实际问题,如教育、医疗咨询、客户服务等领域,并评估其实际效果。

    这些探索点可以帮助研究者和开发者更好地理解GLM-4模型的潜力和局限性,并指导未来的研究方向。

    Q: 总结一下论文的主要内容

    A: 这篇论文主要介绍了ChatGLM,一个由GLM-130B到GLM-4的不断进化的大型语言模型家族。以下是论文的主要内容概述:

    1. 模型介绍:ChatGLM是一系列大型语言模型,包括GLM-4、GLM-4-Air和GLM-4-9B,它们在中文和英文上进行了高质量的对齐。
    2. 预训练数据:使用多语言文档进行预训练,包括网页、维基百科、书籍、代码和论文等,通过去重、过滤和分词等数据处理步骤。
    3. 模型架构:GLM-4采用了无偏置(除QKV外)、RMSNorm、SwiGLU、二维RoPE和Group Query Attention (GQA)等架构设计。
    4. 后训练对齐:通过监督式微调(SFT)和强化学习(RLHF)等后训练技术,进一步与人类偏好对齐。
    5. 性能评估:GLM-4在多个学术基准上与GPT-4等模型进行了比较,显示出在某些领域的优势,特别是在中文对齐方面。
    6. GLM-4 All Tools:一个特别对齐的模型版本,支持智能代理和相关任务,能够自主选择使用适当的工具来完成任务。
    7. 技术贡献:论文还介绍了一些用于提升LLM性能的技术,如LongAlign、ChatGLM-Math、ChatGLM-RLHF、Self-Contrast、AgentTuning和APAR等。
    8. 安全性和风险:讨论了模型的安全性和风险评估,以及在数据预处理和对齐阶段采取的风险缓解措施。
    9. 开放模型和数据:论文强调了模型和数据的开放性,包括在Hugging Face上的下载量和通过GitHub访问的模型。
    10. 未来工作:论文最后讨论了未来的研究方向,包括开发更强大的模型和推动LLM技术的发展。

    总的来说,这篇论文展示了ChatGLM家族在大型语言模型领域的最新进展,并证明了其在多种任务上与现有最先进模型的竞争力。同时,论文也强调了模型的开放性和安全性,以及未来的研究方向。

  • 大型语言模型的低维适应性微调:LaMDA 的高效之道

    大型语言模型 (LLM) 在自然语言处理 (NLP) 领域展现出非凡的能力,能够解决各种任务。然而,完全微调 LLM 成本高昂,难以在边缘设备上实现。为了解决这个问题,参数高效微调 (PEFT) 技术应运而生,其中一种名为低秩适应 (LoRA) 的方法备受关注。

    LoRA 假设预训练权重的变化存在于低秩空间中,因此在模型的冻结主路径中添加两个可训练的低秩适配器,称为投影矩阵 A (PMA) 和投影矩阵 B (PMB)。这种方法虽然减少了可训练参数数量,但随着模型嵌入维度的增加,LoRA 的可训练参数需求也会增加,导致计算成本高昂。此外,LoRA 的反向更新需要存储高维中间激活和优化器状态,对 GPU 内存峰值提出了很高的要求。

    为了解决这些问题,本文介绍了一种名为 LaMDA 的新方法,它利用低维适应来显著减少可训练参数和 GPU 内存峰值。LaMDA 在适应路径中冻结第一个投影矩阵 (PMA),同时引入一个低维可训练方阵,从而大幅减少可训练参数和 GPU 内存峰值。LaMDA 在早期微调阶段逐渐冻结第二个投影矩阵 (PMB),进一步降低与权重更新相关的计算成本,提高参数效率。

    此外,本文还介绍了 LaMDA 的增强版 LaMDA++,它通过对预训练模型权重的规范化频谱分析,为 LoRA 路径引入了“轻量级”自适应秩分配。

    LaMDA:低维适配器的魅力

    LaMDA 的核心是低维适配器 (LDA),它是一个 r 维方阵,其中 r 远小于模型的嵌入维度 d。LaMDA 将 PMA 冻结,而 LDA 始终可训练,PMB 则根据奇异值的相对大小逐渐冻结。这种设计使得可训练参数与 d 无关,并且用于反向传播的激活存储在 r 维空间中,从而显著减少可训练参数、激活和优化器状态内存。

    LaMDA 的优势:

    • 减少可训练参数: LaMDA 的可训练参数数量仅为 LoRA 的 r2,与模型的嵌入维度 d 无关,有效地限制了参数数量,降低了过拟合风险,提高了模型的泛化能力。
    • 降低计算成本: 由于可训练参数数量减少,LaMDA 的反向传播计算量也大幅降低,减少了梯度更新和优化器状态计算,减轻了微调的整体计算和优化器存储开销。
    • 节省内存: LaMDA 将激活存储在 r 维空间中,显著减少了激活内存使用,从而可以微调更大的模型或使用更大的批次大小。

    LaMDA++:自适应秩分配的优化

    LaMDA++ 在 LaMDA 的基础上,引入了自适应秩分配机制,根据预训练模型权重的能量得分,为不同层分配不同的秩。

    LaMDA++ 的优势:

    • 更有效地利用参数预算: LaMDA++ 通过分析预训练模型权重的能量得分,将更多的秩分配给对秩减少影响较小的层,而将更少的秩分配给对秩减少影响较大的层,从而更有效地利用参数预算。
    • 简化实现和使用: LaMDA++ 采用“轻量级”静态分析方法,避免了动态调整秩带来的复杂性和计算开销,简化了实现和使用。

    实验结果

    本文对 LaMDA 和 LaMDA++ 在自然语言理解 (NLU)、自然语言生成 (NLG) 和推理任务上进行了评估,结果表明:

    • NLU 任务: LaMDA 在 GLUE 基准测试中取得了与 LoRA 相当的性能,但可训练参数数量减少了 17.7 倍。LaMDA++ 则取得了最优性能,参数数量略有增加。
    • NLG 任务: LaMDA 在 XSUM 和 CNN/DailyMail 数据集上取得了与 LoRA 相当的性能,但可训练参数数量减少了 10 倍。LaMDA++ 在 XSUM 数据集上超越了 LoRA,在 CNN/DailyMail 数据集上与 LoRA 性能相当。
    • 推理任务: LaMDA 和 LaMDA++ 在 GSM8K 和 Wikitext-2 数据集上都超越了 LoRA。LaMDA 在 Commonsense170K 数据集上取得了比 LoRA 更高的平均准确率,同时可训练参数数量减少了 11.5 倍。

    结论

    LaMDA 是一种新颖的 LLM 微调框架,它利用低维适配器,显著减少了可训练参数数量,节省了激活内存,并通过自适应秩分配进一步优化了性能。LaMDA 和 LaMDA++ 能够有效地微调更大的模型,为模型适应提供了一种高效且可扩展的方法。

    参考文献

    • Hu, Y., et al. (2022). Lora: Low-rank adaptation of large language models. arXiv preprint arXiv:2106.09685.
    • Kopiczko, R., et al. (2024). Vera: Parameter-efficient fine-tuning by projecting to a low-dimensional subspace. arXiv preprint arXiv:2310.17678.
    • Pan, X., et al. (2024a). AdaLoRA: Adaptive low-rank adaptation of large language models. arXiv preprint arXiv:2305.11720.
    • Liu, Z., et al. (2024). AFLoRA: Adaptive frozen low-rank adaptation for efficient large language model fine-tuning. arXiv preprint arXiv:2310.16125.
    • Meng, Z., et al. (2024). On the importance of adapter initialization for parameter-efficient fine-tuning of large language models. arXiv preprint arXiv:2310.17463.

    Q: 这篇论文试图解决什么问题?

    A: 这篇论文介绍了一种名为LaMDA(Large Model Fine-tuning via Spectrally Decomposed Low-Dimensional Adaptation)的新方法,旨在解决大型语言模型(LLMs)微调过程中的两个主要问题:

    1. 训练参数需求随着模型嵌入维度的增加而增加:传统的低秩适应(LoRA)方法在微调大型语言模型时,虽然减少了可训练参数的数量,但当模型的嵌入维度增大时,所需的训练参数数量仍然可能很大。
    2. 高计算成本和GPU内存占用:LoRA方法在反向更新过程中需要存储高维中间激活和优化器状态,这导致GPU内存需求高,尤其在模型参数过多的情况下,容易造成过度拟合和灾难性遗忘。

    为了解决这些问题,LaMDA采用了低维适应技术,通过冻结第一投影矩阵(PMA)并引入一个低维可训练的方阵,显着减少了可训练参数和GPU内存占用。此外,LaMDA在微调的早期阶段逐步冻结第二投影矩阵(PMB),进一步降低与权重更新相关的计算成本,提高参数效率。论文还提出了LaMDA++,一种增强版的方法,通过对方阵进行“轻量级”的自适应秩分配,利用预训练模型权重的归一化谱分析来优化LoRA路径。

    总的来说,LaMDA和LaMDA++旨在提供一种更为高效和可扩展的方式来微调大型语言模型,减少所需的训练参数和内存占用,同时保持或提高模型性能。

    Q: 有哪些相关研究?

    A: 论文中提到了几种与LaMDA相关的研究和技术,主要包括以下几种:

    1. LoRA (Low-rank Adaptation) (Hu et al., 2022): 一种流行的微调大型语言模型的方法,通过添加两个可训练的低秩适配器来减少训练参数的数量。
    2. VERA (Vector-based Random Matrix Adaptation) (Kopiczko et al., 2024): 一种不同的方法,通过随机初始化和冻结PMA和PMB,专注于微调两个特征转换矢量。
    3. AFLoRA (Adaptive Freezing LoRA) (Liu et al., 2024): 为了解决VERA的计算效率问题而提出的方法,但仍然存在高激活存储开销。
    4. LISA (Layerwise Importance Sampling for Memory-efficient Fine-tuning) (Pan et al., 2024b): 一种针对内存效率优化的微调方法。
    5. AdaLoRA: LoRA的一个变种,通过动态学习适配器的秩来提高微调预算的利用效率。
    6. DeBERTa-V3 (He et al., 2023): 用于自然语言理解任务的编码器模型。
    7. BART-Large (Lewis et al., 2020): 用于文本摘要和自然语言生成任务的编码器-解码器模型。
    8. LLaMA2-7B (Touvron et al., 2023b): 用于复杂推理任务的解码器模型。
    9. Transformer-based models (Vaswani et al., 2017): 论文中还讨论了基于Transformer的模型的背景,这些模型通常由多头自注意力(MHSA)子块和前馈网络(FFN)组成。

    这些研究和技术为LaMDA提供了理论基础和比较基准,使得LaMDA能够在减少训练参数和降低GPU内存占用方面取得显着进步。

    Q: 论文如何解决这个问题?

    A: 论文通过提出LaMDA(Large Model Fine-tuning via Spectrally Decomposed Low-Dimensional Adaptation)框架解决了大型语言模型(LLMs)微调过程中遇到的高参数需求和高计算成本问题。以下是LaMDA解决这些问题的关键步骤和方法:

    1. 低维适配器(Low-Dimensional Adapter, LDA)
      • LaMDA引入了一个低维的可训练方阵LDA,该方阵在r维空间中,与模型的嵌入维度d相比,r通常小得多。
    2. 冻结投影矩阵(Projection Matrix Freezing)
      • 在微调过程中,LaMDA冻结了第一投影矩阵(PMA),并只训练LDA,从而显着减少了可训练参数的数量。
    3. 逐步冻结第二投影矩阵(Gradual Freezing of the Second Projection Matrix, PMB)
      • LaMDA在微调的早期阶段逐步冻结PMB,这有助于在保持LaMDA优势的同时提高模型对复杂任务的适应性。
    4. LaMDA++(增强版LaMDA)
      • 利用预训练模型权重的归一化谱分析,为每层的LDA自适应地分配秩,从而实现更优的参数分布。
    5. 初始化策略
      • LaMDA使用奇异值分解(SVD)对预训练权重进行分解,并用对应的奇异矢量初始化PMA和PMB,这有助于在微调开始时近似原始权重。
    6. 内存和计算效率
      • 由于LDA的使用和PMA的冻结,LaMDA在反向传播过程中减少了激活存储的需求,从而降低了GPU内存的使用。
    7. 实验验证
      • 论文通过在多种任务和不同大小的LLMs上进行实验,验证了LaMDA与现有方法相比,在减少参数更新数量和降低GPU内存使用方面的优势。
    8. 性能对比
      • 实验结果显示,LaMDA在保持或提高性能的同时,相比于现有方法,需要更少的参数更新和更低的GPU内存占用。

    通过这些方法,LaMDA在减少训练参数、降低内存占用和计算成本方面取得了显着的改进,同时保持了或提高了模型性能。

    Q: 论文做了哪些实验?

    A: 论文中进行了一系列的实验来评估LaMDA和LaMDA++方法的性能。以下是实验的主要方面:

    1. 模型和数据集:实验涵盖了不同类型的模型,包括编码器(DeBERTa-V3)、编码器-解码器(BART-large)和解码器(LLaMA2-7B)模型。使用了多个数据集,如GLUE基准测试用于自然语言理解(NLU),XSUM和CNN/DailyMail用于文本摘要(NLG),以及GSM8K、Wikitext-2和Commonsense170K用于复杂推理任务。
    2. 微调方法比较:LaMDA与全参数微调(Full FT)、LoRA、LoRA-FA、AdaLoRA、VERA、AFLoRA和LISA等现有的参数高效微调(PEFT)技术进行了比较。
    3. 性能指标:根据不同任务的性质,使用了不同的性能指标,例如GLUE基准上的准确率、文本摘要任务上的ROUGE分数、复杂推理任务上的准确率以及Wikitext-2上的困惑度(Perplexity)。
    4. 可训练参数数量:实验报告了LaMDA和LaMDA++与基线方法相比在减少可训练参数数量方面的效果。
    5. GPU内存使用情况:通过在不同批处理大小下对BART-large模型进行微调,测量了不同微调方法在峰值GPU内存使用上的差异。
    6. LaMDA++的秩分配策略:通过分析预训练模型权重的归一化能量得分,评估了LaMDA++的自适应秩分配策略的有效性。
    7. 初始化选择的影响:研究了不同初始化方法(如使用最大奇异值对应的奇异矢量、随机初始化等)对LaMDA性能的影响。
    8. 逐步冻结PMB的迭代次数:研究了在微调过程中逐步冻结PMB的迭代次数对LaMDA性能的影响。
    9. LaMDA++排名的影响:评估了LaMDA++根据能量得分对层进行排序并分配秩的策略对训练过程和性能的影响。
    10. 常识推理任务:在多个常识推理数据集上评估了LaMDA的性能,包括BoolQ、PIQA、SIQA、HellaSwag、WinoGrande、ARC-e、ARC-c和OBQA。

    这些实验结果表明,LaMDA和LaMDA++在减少可训练参数数量和降低GPU内存需求的同时,能够与或超越现有方法的性能。

    Q: 有什么可以进一步探索的点?

    A: 根据论文的讨论和结论部分,以下是一些可以进一步探索的点:

    1. 在更大模型上的测试:论文中提到,他们测试的最大模型是LLaMA2-7B。由于时间限制,他们未能在更大的模型上测试LaMDA。未来的工作可以在更大的模型上评估LaMDA的可扩展性和有效性。
    2. 在指令遵循任务上的应用:LaMDA尚未在指令遵循任务上进行测试。评估LaMDA在这些特定任务上的性能对于完全理解其潜力和多功能性至关重要。
    3. 应用于视觉-语言模型:论文没有探索LaMDA方法在视觉-语言模型上的应用。考虑到多模态学习的重要性,将LaMDA应用于这类模型是一个值得探索的方向。
    4. 改进的秩分配策略:尽管LaMDA++采用了基于能量得分的秩分配策略,但可能存在更精细或更动态的秩分配方法,这些方法可以进一步优化模型性能和参数效率。
    5. 长期维护和灾难性遗忘问题:在持续微调过程中,研究LaMDA如何处理长期维护问题和灾难性遗忘问题,以及如何改进以减少这些问题的影响。
    6. 不同领域的适应性:研究LaMDA在不同领域(如医疗、法律等专业领域)的适应性,以及是否需要针对特定领域进行调整。
    7. 与其他微调技术的比较:与其他新兴的微调技术进行比较,以评估LaMDA在不同方面(如速度、内存效率、易用性等)的相对优势和局限性。
    8. 模型解释性和可理解性:提高LaMDA微调过程中模型的解释性和可理解性,帮助研究人员和实践者更好地理解模型的决策过程。
    9. 跨语言评估:评估LaMDA在不同语言上的微调效果,以及它如何处理语言之间的差异。
    10. 环境影响评估:研究LaMDA在减少计算资源需求的同时,对环境影响(如能源消耗和碳足迹)的潜在影响。

    这些探索点可以帮助研究者更深入地理解LaMDA的潜力,并推动大型语言模型微调技术的发展。

    Q: 总结一下论文的主要内容

    A: 这篇论文介绍了LaMDA,一种用于大型语言模型(LLMs)微调的新方法。以下是论文的主要内容总结:

    1. 问题识别:论文首先指出了现有微调大型语言模型方法(如LoRA)存在的问题,包括随着模型尺寸增加而增加的参数需求,以及高计算成本和GPU内存占用。
    2. LaMDA方法:提出了LaMDA方法,它通过使用低维适配器(LDA)和逐步冻结第二投影矩阵(PMB)来减少可训练参数和GPU内存占用。
    3. LaMDA++:介绍了LaMDA的增强版LaMDA++,它通过归一化谱分析自适应地为不同层分配秩,以优化参数分布。
    4. 实验设置:论文详细描述了实验的设置,包括使用的不同模型(DeBERTa-V3、BART-large、LLaMA2-7B)和数据集(GLUE、XSUM、CNN/DailyMail、GSM8K、Wikitext-2等)。
    5. 性能比较:展示了LaMDA和LaMDA++与现有微调方法(包括Full FT、LoRA、AdaLoRA、VERA、AFLoRA和LISA)的性能比较,证明了LaMDA在减少参数数量和降低GPU内存使用方面的优势。
    6. 内存和计算效率:通过实验数据,论文展示了LaMDA在不同批处理大小下对BART-large模型微调时的内存效率。
    7. 初始化和秩分配策略:研究了不同的初始化方法和LaMDA++的秩分配策略对性能的影响。
    8. 逐步冻结PMB的影响:分析了逐步冻结PMB的迭代次数对LaMDA性能的影响。
    9. 常识推理任务:在多个常识推理数据集上评估了LaMDA的性能,并与LoRA进行了比较。
    10. 结论和局限性:论文总结了LaMDA的主要贡献,并指出了研究的局限性,如未在更大的模型和指令遵循任务上进行测试,以及未探索在视觉-语言模型上的应用。
    11. 未来工作:提出了未来可能的研究方向,包括在更大模型上的测试、指令遵循任务、视觉-语言模型应用等。

    论文的代码将在GitHub上公开,以供研究社区使用和进一步研究。

  • 大型语言模型驱动的智能体:从诞生到社会

    近年来,人工智能领域取得了令人瞩目的进展,其中大型语言模型(LLM)的出现被认为是通向通用人工智能(AGI)的关键一步。LLM 拥有强大的语言理解和生成能力,为构建能够感知环境、做出决策并执行行动的智能体提供了坚实的基础。本文将深入探讨 LLM 驱动的智能体,从其构建、应用到社会模拟等方面展开论述。

    1. 智能体的诞生:LLM 驱动的智能体构建

    LLM 驱动的智能体通常由三个主要部分组成:大脑感知行动

    1.1 大脑:以 LLM 为核心

    LLM 是智能体的大脑,赋予其强大的语言能力,使其能够理解和生成自然语言。

    1.1.1 自然语言交互

    LLM 在自然语言交互方面展现出卓越的能力,包括:

    1.1.2 知识

    LLM 的知识储备是其强大能力的基石,主要来源包括:

    1.1.3 内存

    LLM 的内存能力决定了其记忆和检索信息的能力。

    1.1.4 推理与规划

    LLM 的推理和规划能力是其解决复杂问题、制定行动计划的关键。

    1.1.5 可迁移性和泛化性

    LLM 的可迁移性和泛化性决定了其在不同任务和场景下的适应能力。

    1.2 感知:多模态输入

    LLM 驱动的智能体可以通过多模态感知,获取更丰富的信息。

    1.2.1 视觉

    LLM 可以理解和生成图像信息,例如,Images Speak in Images: A Generalist Painter for In-Context Visual Learning 提出了一个用于上下文视觉学习的通用模型 Painter。

    1.2.2 音频

    LLM 可以理解和生成音频信息,例如,Neural Codec Language Models are Zero-Shot Text to Speech Synthesizers 训练了一个神经编解码语言模型 VALL-E,具备上下文学习能力。

    1.3 行动:扩展行动空间

    LLM 驱动的智能体可以通过工具使用和具身行动,扩展其行动能力。

    1.3.1 工具使用

    LLM 可以使用外部工具来完成任务,例如,ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs 提出了一种通用的工具使用框架 ToolLLM,可以帮助 LLM 使用各种 API。

    1.3.2 具身行动

    LLM 可以控制机器人等具身智能体,在物理环境中执行任务,例如,PaLM-E: An Embodied Multimodal Language Model 提出了一种具身多模态语言模型 PaLM-E,可以进行具身行动。

    2. 智能体在实践中:LLM 驱动的智能体应用

    LLM 驱动的智能体在各个领域展现出巨大的应用潜力。

    2.1 单个智能体的通用能力

    2.1.1 任务导向部署

    LLM 驱动的智能体可以用于完成各种特定任务,例如:

    2.1.2 创新导向部署

    LLM 驱动的智能体可以用于推动创新,例如:

    2.1.3 生命周期导向部署

    LLM 驱动的智能体可以用于模拟生物的生命周期,例如:

    2.2 多个智能体的协调潜力

    2.2.1 合作交互以实现互补

    LLM 驱动的智能体可以协同合作,发挥各自的优势,例如:

    2.2.2 对抗交互以实现进步

    LLM 驱动的智能体可以通过对抗交互,提升各自的能力,例如:

    2.3 人机交互

    2.3.1 指导者-执行者模式

    LLM 驱动的智能体可以作为人类的助手,执行指令,例如:

    2.3.2 平等伙伴模式

    LLM 驱动的智能体可以作为人类的伙伴,进行平等的交流和合作,例如:

    3. 智能体社会:从个体到群体

    LLM 驱动的智能体可以形成社会,模拟人类社会的行为和现象。

    3.1 LLM 驱动的智能体的行为和个性

    3.1.1 社会行为
    3.1.2 个性

    3.2 智能体社会环境

    3.2.1 文本环境

    LLM 驱动的智能体可以在文本环境中进行交互,例如,Hoodwinked: Deception and Cooperation in a Text-Based Game for Language Models 展示了 LLM 在文本游戏中的应用。

    3.2.2 虚拟沙盒环境

    LLM 驱动的智能体可以在虚拟沙盒环境中进行模拟,例如,Generative Agents: Interactive Simulacra of Human Behavior 展示了 LLM 在虚拟环境中的应用。

    3.2.3 物理环境

    LLM 驱动的智能体可以控制机器人等具身智能体,在物理环境中进行交互,例如,RoboAgent: Generalization and Efficiency in Robot Manipulation via Semantic Augmentations and Action Chunking 展示了 LLM 在机器人控制中的应用。

    3.3 基于 LLM 的智能体社会模拟

    LLM 驱动的智能体可以用于模拟人类社会,例如:

    4. 未来展望:机遇与挑战并存

    LLM 驱动的智能体正处于快速发展阶段,其强大的语言能力、知识储备、推理规划能力以及可迁移性和泛化性,使其在各种领域展现出巨大潜力。然而,我们也必须清醒地认识到,这项技术的发展并非一帆风顺,还面临着许多挑战和风险。

    4.1 互相促进:LLM 与智能体研究的双向赋能

    LLM 研究为智能体研究提供了强大的基础模型,例如,LLM 可以帮助智能体进行决策、规划和行动,并有效地处理未见任务。另一方面,智能体研究也为 LLM 研究提出了新的挑战和方向,例如,如何让 LLM 更好地理解环境、学习新的技能以及进行更有效的社会交互。

    4.2 评价体系:多维评估,确保智能体安全可靠

    评估 LLM 驱动的智能体是一个复杂的过程,需要考虑多个维度:

    4.3 安全与信任:防范风险,构建可信赖的智能体

    LLM 驱动的智能体在应用过程中存在着许多潜在风险,例如:

    为了降低风险,我们需要采取措施,例如:

    • 增强鲁棒性: 通过对抗性训练等方法,提升 LLM 的鲁棒性。
    • 提高可信度: 通过思维链等方法,增强 LLM 的可解释性和可信度。
    • 规范使用: 制定相关政策和标准,规范 LLM 驱动的智能体的使用。

    4.4 规模化:构建更复杂、更真实的智能体社会

    随着智能体数量的增加,我们可以构建更复杂、更真实的智能体社会,例如:

    然而,规模化也带来了新的挑战,例如:

    • 计算负担: 智能体数量的增加会带来巨大的计算负担。
    • 协调难度: 协调大量智能体进行有效的合作和交流会非常困难。
    • 信息失真: 智能体数量的增加可能导致信息失真和传播问题。

    4.5 开放问题:探索未知,展望未来

    LLM 驱动的智能体领域还有许多开放问题需要进一步研究,例如:

    • 通向 AGI 的道路: LLM 驱动的智能体是否能成为通向 AGI 的道路?
    • 从虚拟到现实: 如何将 LLM 驱动的智能体从虚拟环境迁移到真实的物理环境?
    • 群体智能: 如何利用 LLM 驱动的智能体社会来探索群体智能的奥秘?
    • 代理即服务: 如何将 LLM 驱动的智能体作为服务提供给用户?

    5. 结语

    LLM 驱动的智能体正在改变着我们对人工智能的理解,也为我们带来了前所未有的机遇和挑战。未来,我们期待着 LLM 驱动的智能体能够在更多领域发挥作用,为人类社会带来更大的福祉。

    参考文献

    [1] The Rise and Potential of Large Language Model Based Agents: A Survey. Zhiheng Xi et al. (2023). https://arxiv.org/abs/2309.07864

    [2] LLM-Agent-Paper-List. https://github.com/WooooDyy/LLM-Agent-Paper-List

    致谢

    感谢复旦大学自然语言处理团队(FudanNLP)的辛勤付出,为我们带来了这篇精彩的综述论文。

  • MetaGPT 教学助手:一键生成技术教程

    在学习新技术时,一份好的教程可以事半功倍。MetaGPT 的教学助手角色,可以帮助你根据简单的描述,自动生成技术教程文档。

    教学助手的功能

    教学助手可以根据用户提供的单句描述,生成一份技术教程文档,并支持自定义语言。

    设计理念

    教学助手的设计思路是:

    1. 使用大型语言模型 (LLM) 生成教程的大纲。
    2. 根据二级标题将大纲分解成多个部分。
    3. 针对每个部分,根据标题生成详细内容。
    4. 最后将标题和内容拼接起来。

    使用分段的方式,可以解决 LLM 模型处理长文本的限制。

    代码实现

    角色定义

    定义教学助手角色类,继承自 Role 基类,并重写 __init__ 初始化方法。__init__ 方法必须包含 nameprofilegoalconstraints 参数。第一行代码使用 super().__init__(name, profile, goal, constraints) 调用父类的构造函数,初始化 Role。使用 self.set_actions([WriteDirectory(language=language)]) 添加初始动作和状态。这里,最初添加了写目录动作。此外,还可以定义自定义参数;这里添加了 language 参数,用于支持自定义语言。使用 self._set_react_mode(react_mode="by_order")set_actions 中的动作执行顺序设置为顺序执行。

    class TutorialAssistant(Role):
        """教学助手,输入一句话生成一份标记格式的教程文档。
    
        Args:
            name: 角色名称。
            profile: 角色简介。
            goal: 角色目标。
            constraints: 角色的约束或要求。
            language: 生成教程文档的语言。
        """
    
        def __init__(
            self,
            name: str = "Stitch",
            profile: str = "教学助手",
            goal: str = "生成教程文档",
            constraints: str = "严格遵循 Markdown 语法,布局整洁规范",
            language: str = "Chinese",
        ):
            super().__init__(name, profile, goal, constraints)
            self.set_actions([WriteDirectory(language=language)])
            self.topic = ""
            self.main_title = ""
            self.total_content = ""
            self.language = language
            self._set_react_mode(react_mode="by_order")

    重写 react 方法

    重写 react 方法。使用 await super().react() 调用 Role 基类的 react 方法。根据 __init__ 方法中设置的 react_mode="by_order",按顺序执行 states 中的每个动作。这里重写的目的是在完成所有动作后执行最终操作,即:将拼接后的教程内容写入 markdown 文件。

    async def react(self) -> Message:
        msg = await super().react()
        root_path = TUTORIAL_PATH / datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        await File.write(root_path, f"{self.main_title}.md", self.total_content.encode('utf-8'))
        return msg

    重写 _act 方法

    _act 方法负责执行动作。使用 todo = self.rc.todo 从上下文中获取下一个要执行的动作,然后执行动作的 run 方法。这里,它首先通过 WriteDirectory 获取教程目录结构,然后对目录进行分块,为每个块生成一个 WriteContent 动作,并初始化新添加的动作。这里再次调用 await super().react() 是为了从头开始执行所有新添加的 WriteContent 动作。每个动作的结果用于生成一个 Message(content=resp, role=self.profile) 消息,该消息可以放置在上下文记忆 self.rc.memory 中。该角色不需要存储。

    async def _act(self) -> Message:
        todo = self.rc.todo
        if type(todo) is WriteDirectory:
            msg = self.rc.memory.get(k=1)[0]
            self.topic = msg.content
            resp = await todo.run(topic=self.topic)
            logger.info(resp)
            await self._handle_directory(resp)
            return await super().react()
        resp = await todo.run(topic=self.topic)
        logger.info(resp)
        if self.total_content != "":
            self.total_content += "\n\n\n"
        self.total_content += resp
        return Message(content=resp, role=self.profile)
    
    async def _handle_directory(self, titles: Dict) -> Message:
        """处理教程文档的目录。
    
        Args:
            titles: 包含标题和目录结构的字典,
                    例如 {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]}
    
        Returns:
            包含目录信息的 Message。
        """
        self.main_title = titles.get("title")
        directory = f"{self.main_title}\n"
        self.total_content += f"# {self.main_title}"
        actions = list()
        for first_dir in titles.get("directory"):
            actions.append(WriteContent(language=self.language, directory=first_dir))
            key = list(first_dir.keys())[0]
            directory += f"- {key}\n"
            for second_dir in first_dir[key]:
                directory += f"  - {second_dir}\n"
        self.set_actions(actions)

    动作定义

    定义动作,每个动作对应一个类对象。继承自 Action 基类,并重写 __init__ 初始化方法。__init__ 方法包含 name 参数。第一行代码使用 super().__init__(name, *args, **kwargs) 调用父类的构造函数,初始化动作。这里,使用 argskwargs 将其他参数传递给父类构造函数,例如 contextllm

    #!/usr/bin/env python3
    # _*_ coding: utf-8 _*_
    """
    @Time    : 2023/9/4 15:40:40
    @Author  : Stitch-z
    @File    : tutorial_assistant.py
    @Describe : Actions of the tutorial assistant, including writing directories and document content.
    """
    
    from typing import Dict
    
    from metagpt.actions import Action
    from metagpt.prompts.tutorial_assistant import DIRECTORY_PROMPT, CONTENT_PROMPT
    from metagpt.utils.common import OutputParser
    
    
    class WriteDirectory(Action):
        """写教程目录的动作类。
    
        Args:
            name: 动作名称。
            language: 输出语言,默认值为 "Chinese"。
        """
    
        def __init__(self, name: str = "", language: str = "Chinese", *args, **kwargs):
            super().__init__(name, *args, **kwargs)
            self.language = language

    重写 run 方法

    run 方法是动作执行的主要函数,使用 self._aask(prompt=prompt) 方法查询 LLM 模型。

    async def run(self, topic: str, *args, **kwargs) -> Dict:
        """执行动作,根据主题生成教程目录。
    
        Args:
            topic: 教程主题。
    
        Returns:
            教程目录信息,包括 {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]}。
        """
        prompt = DIRECTORY_PROMPT.format(topic=topic, language=self.language)
        resp = await self._aask(prompt=prompt)
        return OutputParser.extract_struct(resp, dict)

    其他动作的编写类似:

    class WriteContent(Action):
        """写教程内容的动作类。
    
        Args:
            name: 动作名称。
            directory: 要写入的内容。
            language: 输出语言,默认值为 "Chinese"。
        """
    
        def __init__(self, name: str = "", directory: str = "", language: str = "Chinese", *args, **kwargs):
            super().__init__(name, *args, **kwargs)
            self.language = language
            self.directory = directory
    
        async def run(self, topic: str, *args, **kwargs) -> str:
            """执行动作,根据目录和主题写入文档内容。
    
            Args:
                topic: 教程主题。
    
            Returns:
                写入的教程内容。
            """
            prompt = CONTENT_PROMPT.format(topic=topic, language=self.language, directory=self.directory)
            return await self._aask(prompt=prompt)

    角色执行结果

    输入示例

    • MySQL 教程
    • Redis 教程
    • Hive 教程

    执行命令示例

    提供相应的执行命令示例。

    执行结果

    生成的教程文档位于项目的 /data/tutorial_docx 目录中。

    注意:

    该角色目前不支持互联网搜索功能。内容生成依赖于 LLM 大模型训练的数据。

    总结

    MetaGPT 的教学助手角色可以帮助你快速生成技术教程文档,并支持自定义语言。它可以节省你大量时间和精力,让你专注于更重要的工作。

    更多学习资源

  • MetaGPT 研究员:让 AI 帮你搜集信息、撰写报告

    在信息爆炸的时代,获取准确可靠的信息并将其整理成简洁易懂的报告,是一项非常重要的技能。MetaGPT 的研究员角色,可以帮助你完成这项任务。

    研究员的角色

    MetaGPT 的研究员角色可以模拟人类在互联网上进行研究的过程。它能够:

    • 分析研究问题,将其分解成多个适合搜索引擎查询的子问题。
    • 使用搜索引擎搜索子问题,并根据标题、原始 URL、摘要等信息评估每个结果的相关性和可靠性。
    • 决定是否需要进一步浏览网页。
    • 点击需要进一步探索的网页,评估内容是否对研究问题有帮助,提取相关信息并记录。
    • 将所有记录的相关信息汇总,并撰写一份解决研究问题的报告。

    研究员的架构

    MetaGPT 的研究员角色包含三个主要动作:

    • CollectLinks: 从搜索引擎收集链接。
    • WebBrowseAndSummarize: 浏览网页并提供摘要。
    • ConductResearch: 进行研究并生成研究报告。

    动作定义

    CollectLinks

    CollectLinks 动作用于搜索互联网以获取相关问题并检索 URL 地址列表。由于用户输入的问题可能不直接适合搜索引擎查询,CollectLinks 动作首先将用户的问题分解成多个适合搜索的子问题。然后,它使用搜索引擎进行搜索。

    实现使用了 tools 模块中的 SearchEngine,支持通过 serpapi/google/serper/ddg 进行搜索。实现细节可以在 metagpt/actions/research.py 文件中找到,以下是对 CollectLinks.run 方法的基本解释:

    class CollectLinks(Action):
    
        async def run(
            self,
            topic: str,
            decomposition_nums: int = 4,
            url_per_query: int = 4,
            system_text: str | None = None,
        ) -> dict[str, list[str]]:
            """运行动作以收集链接。
    
            Args:
                topic: 研究主题。
                decomposition_nums: 要生成的搜索问题的数量。
                url_per_query: 每个搜索问题要收集的 URL 数量。
                system_text: 系统文本。
    
            Returns:
                一个字典,包含搜索问题作为键,收集的 URL 作为值。
            """
            system_text = system_text if system_text else RESEARCH_TOPIC_SYSTEM.format(topic=topic)
            # 将研究问题分解成多个子问题
            keywords = await self._aask(SEARCH_TOPIC_PROMPT, [system_text])
            try:
                keywords = OutputParser.extract_struct(keywords, list)
                keywords = parse_obj_as(list[str], keywords)
            except Exception as e:
                logger.exception(f"fail to get keywords related to the research topic \"{topic}\" for {e}")
                keywords = [topic]
    
            # 使用搜索引擎搜索子问题
            results = await asyncio.gather(*(self.search_engine.run(i, as_string=False) for i in keywords))
    
            # 浏览搜索引擎结果,并过滤掉与研究问题无关的结果
            def gen_msg():
                while True:
                    search_results = "\n".join(f"#### Keyword: {i}\n Search Result: {j}\n" for (i, j) in zip(keywords, results))
                    prompt = SUMMARIZE_SEARCH_PROMPT.format(decomposition_nums=decomposition_nums, search_results=search_results)
                    yield prompt
                    remove = max(results, key=len)
                    remove.pop()
                    if len(remove) == 0:
                        break
            prompt = reduce_message_length(gen_msg(), self.llm.model, system_text, CONFIG.max_tokens_rsp)
            logger.debug(prompt)
            queries = await self._aask(prompt, [system_text])
            try:
                queries = OutputParser.extract_struct(queries, list)
                queries = parse_obj_as(list[str], queries)
            except Exception as e:
                logger.exception(f"fail to break down the research question due to {e}")
                queries = keywords
            ret = {}
    
            # 对搜索结果进行排序,并获取 TopK URL
            for query in queries:
                ret[query] = await self._search_and_rank_urls(topic, query, url_per_query)
            return ret

    WebBrowseAndSummarize

    WebBrowseAndSummarize 动作负责浏览网页并对其内容进行摘要。MetaGPT 在 tools 模块中提供了 WebBrowserEngine,它支持通过 playwright/selenium 进行网页浏览。WebBrowseAndSummarize 动作使用 WebBrowserEngine 进行网页浏览。

    实现细节可以在 metagpt/actions/research.py 文件中找到,以下是对 WebBrowseAndSummarize.run 方法的基本解释:

    class WebBrowseAndSummarize(Action):
        async def run(
            self,
            url: str,
            *urls: str,
            query: str,
            system_text: str = RESEARCH_BASE_SYSTEM,
        ) -> dict[str, str]:
            """运行动作以浏览网页并提供摘要。
    
            Args:
                url: 要浏览的主要 URL。
                urls: 要浏览的其他 URL。
                query: 研究问题。
                system_text: 系统文本。
    
            Returns:
                一个字典,包含 URL 作为键,其摘要作为值。
            """
            # 网页浏览和内容提取
            contents = await self.web_browser_engine.run(url, *urls)
            if not urls:
                contents = [contents]
    
            # 网页内容摘要
            summaries = {}
            prompt_template = WEB_BROWSE_AND_SUMMARIZE_PROMPT.format(query=query, content="{}")
            for u, content in zip([url, *urls], contents):
                content = content.inner_text
                chunk_summaries = []
                for prompt in generate_prompt_chunk(content, prompt_template, self.llm.model, system_text, CONFIG.max_tokens_rsp):
                    logger.debug(prompt)
                    summary = await self._aask(prompt, [system_text])
                    if summary == "Not relevant.":
                        continue
                    chunk_summaries.append(summary)
    
                if not chunk_summaries:
                    summaries[u] = None
                    continue
    
                if len(chunk_summaries) == 1:
                    summaries[u] = chunk_summaries[0]
                    continue
    
                content = "\n".join(chunk_summaries)
                prompt = WEB_BROWSE_AND_SUMMARIZE_PROMPT.format(query=query, content=content)
                summary = await self._aask(prompt, [system_text])
                summaries[u] = summary
            return summaries

    ConductResearch

    ConductResearch 动作负责撰写研究报告。它使用 WebBrowseAndSummarize 动作的摘要数据作为上下文,然后生成研究报告。

    实现细节可以在 metagpt/actions/research.py 文件中找到,以下是对 ConductResearch.run 方法的基本解释:

    class ConductResearch(Action):
        async def run(
            self,
            topic: str,
            content: str,
            system_text: str = RESEARCH_BASE_SYSTEM,
        ) -> str:
            """运行动作以进行研究并生成研究报告。
    
            Args:
                topic: 研究主题。
                content: 研究内容。
                system_text: 系统文本。
    
            Returns:
                生成的 research report。
            """
            prompt = CONDUCT_RESEARCH_PROMPT.format(topic=topic, content=content)
            logger.debug(prompt)
            self.llm.auto_max_tokens = True
            return await self._aask(prompt, [system_text])

    研究员角色

    研究员角色将 CollectLinksWebBrowseAndSummarizeConductResearch 动作结合在一起,实现了搜索互联网并汇总报告的功能。因此,在初始化时需要使用 set_actions 方法将这三个动作添加到角色中。由于这些动作按照 CollectLinks -> WebBrowseAndSummarize -> ConductResearch 的顺序执行,因此需要在 react/_act 方法中定义这些动作的执行逻辑。

    实现细节可以在 metagpt/roles/researcher.py 文件中找到,以下是对 Researcher 类的基本解释:

    class Researcher(Role):
        def __init__(
            self,
            name: str = "David",
            profile: str = "Researcher",
            goal: str = "Gather information and conduct research",
            constraints: str = "Ensure accuracy and relevance of information",
            language: str = "en-us",
            **kwargs,
        ):
            super().__init__(name, profile, goal, constraints, **kwargs)
    
            # 添加 `CollectLinks`、`WebBrowseAndSummarize` 和 `ConductResearch` 动作
            self.set_actions([CollectLinks(name), WebBrowseAndSummarize(name), ConductResearch(name)])
    
            # 设置按顺序执行
            self._set_react_mode(react_mode="by_order")
            self.language = language
            if language not in ("en-us", "zh-cn"):
                logger.warning(f"The language `{language}` has not been tested, it may not work.")
    
        async def _act(self) -> Message:
            logger.info(f"{self._setting}: ready to {self.rc.todo}")
            todo = self.rc.todo
            msg = self.rc.memory.get(k=1)[0]
            if isinstance(msg.instruct_content, Report):
                instruct_content = msg.instruct_content
                topic = instruct_content.topic
            else:
                topic = msg.content
    
            research_system_text = get_research_system_text(topic, self.language)
            # 搜索互联网并检索 URL 信息
            if isinstance(todo, CollectLinks):
                links = await todo.run(topic, 4, 4)
                ret = Message(content="", instruct_content=Report(topic=topic, links=links), role=self.profile, cause_by=todo)
            # 浏览网页并对其内容进行摘要
            elif isinstance(todo, WebBrowseAndSummarize):
                links = instruct_content.links
                todos = (todo.run(*url, query=query, system_text=research_system_text) for (query, url) in links.items())
                summaries = await asyncio.gather(*todos)
                summaries = list((url, summary) for i in summaries for (url, summary) in i.items() if summary)
                ret = Message(content="", instruct_content=Report(topic=topic, summaries=summaries), role=self.profile, cause_by=todo)
            # 生成 research report
            else:
                summaries = instruct_content.summaries
                summary_text = "\n---\n".join(f"url: {url}\nsummary: {summary}" for (url, summary) in summaries)
                content = await self.rc.todo.run(topic, summary_text, system_text=research_system_text)
                ret = Message(content="", instruct_content=Report(topic=topic, content=content), role=self.profile, cause_by=type(self.rc.todo))
            self.rc.memory.add(ret)
            return ret
    
        async def react(self) -> Message:
            msg = await super().react()
            report = msg.instruct_content
            # 输出 report
            self.write_report(report.topic, report.content)
            return msg

    使用说明

    依赖和配置

    研究员角色依赖于 SearchEngineWebBrowserEngine。以下是安装和配置这些组件的简要说明。

    SearchEngine

    支持 serpapi/google/serper/ddg 搜索引擎。它们的区别如下:

    名称默认引擎附加依赖包安装
    serpapipip install metagpt[search-google]
    google×google-api-python-clientpip install metagpt[search-google]
    serper×
    ddg×duckduckgo-searchpip install metagpt[search-ddg]

    配置:

    WebBrowserEngine

    支持 playwright/selenium 引擎。要使用它们,必须安装额外的依赖项。它们的区别如下:

    名称默认引擎附加依赖包安装异步支持的平台
    playwrightplaywright, beautifulsoup4pip install metagpt[playwright]Native部分支持的平台
    selenium×selenium, webdriver_manager, beautifulsoup4pip install metagpt[selenium]线程池几乎所有平台

    配置:

    • playwright:
      • browser.engine: 设置为 playwright
      • browser.browser_type: 支持 chromium/firefox/webkit,默认值为 chromium。更多信息: Playwright BrowserTypes
    • selenium:
      • browser.engine: 设置为 selenium
      • browser.browser_type: 支持 chrome/firefox/edge/ie,默认值为 chrome。更多信息: Selenium BrowserTypes

    运行示例和结果

    metagpt.roles.researcher 模块提供了一个命令行界面,用于执行研究员的功能。以下是一个示例:

    python3 -m metagpt.roles.researcher "tensorflow vs. pytorch"

    日志输出:log.txt
    报告输出:dataiku vs. datarobot.md

    总结

    MetaGPT 的研究员角色可以帮助你快速高效地从互联网上搜集信息并撰写研究报告。它可以节省你大量时间和精力,让你专注于更重要的工作。

    更多学习资源

  • MetaGPT 数据可视化:让数据说话

    MetaGPT 数据可视化:让数据说话

    数据可视化是将数据以图表、图形等视觉形式呈现的过程,它可以帮助我们发现数据中的模式、趋势和相关性,并提供洞察和理解。通过数据可视化,我们可以更好地理解数据的含义,传达和解释结果,并支持数据驱动的决策和沟通。

    示例:可视化鸢尾花数据集

    任务: 使用 DataInterpreter 对 sklearn 的鸢尾花数据集进行简单的分析和可视化。

    代码:

    python examples/di/data_visualization.py

    examples/di/data_visualization.py 文件中的代码如下:

    import asyncio
    from metagpt.logs import logger
    from metagpt.roles.di.data_interpreter import DataInterpreter
    from metagpt.utils.recovery_util import save_history
    
    async def main(requirement: str = ""):
    
        di = DataInterpreter()
        rsp = await di.run(requirement)
        logger.info(rsp)
        save_history(role=di)
    
    
    if __name__ == "__main__":
    
        requirement = "对 sklearn 的鸢尾花数据集进行数据分析,并包含一个图表"
        asyncio.run(main(requirement))

    执行上述代码后,生成的计划和代码将分别保存在 data/output/current_time/plan.jsondata/output/current_time/code.ipynb 文件中。

    执行结果

    DataInterpreter 提出了以下解决方案任务:

    [
      {
        "task_id": "1",
        "dependent_task_ids": [],
        "instruction": "从 sklearn 加载鸢尾花数据集。"
      },
      {
        "task_id": "2",
        "dependent_task_ids": ["1"],
        "instruction": "对鸢尾花数据集进行探索性数据分析。"
      },
      {
        "task_id": "3",
        "dependent_task_ids": ["2"],
        "instruction": "创建图表来可视化鸢尾花数据集的特征。"
      }
    ]

    DataInterpreter 能够将问题分解成逻辑任务,并按照加载数据、分析数据和绘制图表步骤进行执行。

    DataInterpreter 生成的代码如下:

    # ----------------------------------task1------------------------------------
    from sklearn.datasets import load_iris
    iris_data = load_iris()
    iris_data.keys()
    !pip install scikit-learn
    from sklearn.datasets import load_iris
    iris_data = load_iris()
    iris_data.keys()
    # ----------------------------------task2------------------------------------
    import pandas as pd
    
    # 从鸢尾花数据集创建 DataFrame
    iris_df = pd.DataFrame(iris_data['data'], columns=iris_data['feature_names'])
    iris_df['species'] = pd.Categorical.from_codes(iris_data['target'], iris_data['target_names'])
    
    # 汇总统计
    summary_statistics = iris_df.describe()
    
    # 检查缺失值
    missing_values = iris_df.isnull().sum()
    
    (summary_statistics, missing_values)
    # ----------------------------------task3------------------------------------
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    # 使用 seaborn 的 pairplot 可视化数据集特征
    sns.set(style='whitegrid', context='notebook')
    iris_pairplot = sns.pairplot(iris_df, hue='species', height=2.5)
    plt.show()

    在执行任务 1 时,由于环境中缺少 scikit-learn,第一次执行时发生了错误。但是,DataInterpreter 能够分析并解决这个问题,通过安装 scikit-learn 来解决。在任务 3 中,DataInterpreter 使用 seaborn 的 pairplot 函数创建了一个散点图矩阵,它可视化了数据集不同特征之间的关系,并使用颜色区分了不同物种的数据点。最后,使用 plt.show() 显示图表。

    以下是 DataInterpreter 运行代码后绘制的图表。很明显,代码成功执行并生成了一个漂亮的可视化表格,它可以帮助我们更有效地分析数据集的特征。

    总结

    这个例子展示了 DataInterpreter 如何使用数据可视化来帮助我们分析和理解数据。它能够自动生成代码,并根据我们的需求选择合适的可视化方法。

    更多学习资源

  • MetaGPT:让你的 AI 团队个性十足

    在之前的教程中,我们学习了如何整合开源 LLM,让你的 AI 团队更强大。但你是否想过,如何让团队中的每个成员都拥有独特的个性和能力?

    MetaGPT 允许你为不同的角色和动作指定不同的 LLM,让你的 AI 团队更加灵活和真实。

    个性化配置

    MetaGPT 提供了两种方式来定制 LLM 配置:

    1. 默认配置: MetaGPT 提供了一些默认配置,你可以直接使用。
    2. 自定义配置: 你可以在 ~/.metagpt 目录中创建自定义配置文件。

    示例:

    假设你想为 GPT-4、GPT-4-turbo 和 GPT-3.5-turbo 创建配置:

    from metagpt.config2 import Config
    
    # 示例配置:gpt-4、gpt-4-turbo 和 gpt-3.5-turbo
    gpt4 = Config.from_home("gpt-4.yaml")  # 从 `~/.metagpt` 目录加载 `gpt-4.yaml` 文件中的自定义配置
    gpt4t = Config.default()  # 使用 `config2.yaml` 文件中的默认配置 (模型: "gpt-4-turbo")
    gpt35 = Config.default()
    gpt35.llm.model = "gpt-3.5-turbo"  # 将模型修改为 "gpt-3.5-turbo"

    分配配置

    创建配置后,你可以将它们分配给不同的角色和动作。

    优先级:

    • 动作配置 > 角色配置 > 全局配置 ( config2.yaml 文件中的配置)

    示例:

    假设你想要创建一个模拟美国大选直播的环境,包含三个角色:

    • A: 民主党候选人
    • B: 共和党候选人
    • C: 选民
    from metagpt.roles import Role
    from metagpt.actions import Action
    
    # 创建三个动作:a1、a2 和 a3。将 gpt4t 的配置分配给 a1。
    a1 = Action(config=gpt4t, name="Say", instruction="用感情表达你的观点,不要重复")
    a2 = Action(name="Say", instruction="用感情表达你的观点,不要重复")
    a3 = Action(name="Vote", instruction="投票给候选人,并说明你为什么投票给他/她")
    
    # 创建三个角色:A、B 和 C。分别代表“民主党候选人”、“共和党候选人”和“选民”。
    # 虽然 A 在角色配置中配置了 gpt4,但由于动作配置设置,它将使用模型 gpt4t 的配置来执行 a1。
    A = Role(name="A", profile="民主党候选人", goal="赢得选举", actions=[a1], watch=[a2], config=gpt4)
    # 由于 B 在角色配置中配置了 gpt35,而 a2 没有动作配置,B 和 a2 都将使用角色配置,即模型 gpt35 的配置。
    B = Role(name="B", profile="共和党候选人", goal="赢得选举", actions=[a2], watch=[a1], config=gpt35)
    # 由于 C 没有设置配置,a3 也没有设置配置,C 和 a3 都将使用全局配置,即模型 gpt4 的配置。
    C = Role(name="C", profile="选民", goal="投票给候选人", actions=[a3], watch=[a1, a2])

    团队交互

    完成配置后,你可以创建一个团队,并让它们进行交互。

    示例:

    import asyncio
    from metagpt.environment import Environment
    from metagpt.team import Team
    
    # 创建一个名为“美国大选直播”的环境
    env = Environment(desc="美国大选直播")
    team = Team(investment=10.0, env=env, roles=[A, B, C])
    # 运行团队,你应该能观察到它们之间的协作
    asyncio.run(team.run(idea="主题:气候变化。每条消息不超过 80 个字。", send_to="A", n_round=3))
    # await team.run(idea="主题:气候变化。每条消息不超过 80 个字。", send_to="A", n_round=3) # 如果在 Jupyter Notebook 中运行,使用此代码行

    总结

    本教程展示了如何使用 MetaGPT 为不同的角色和动作指定不同的 LLM,让你的 AI 团队更加灵活和真实。通过个性化配置,你可以让你的 AI 团队更加符合你的需求,并创造更加沉浸式的交互体验。

    更多学习资源

  • MetaGPT 与开源 LLM 的整合:让你的 AI 团队更强大

    在之前的教程中,我们学习了如何创建和使用智能体、工具以及人机协作。但 MetaGPT 的真正强大之处在于它能够灵活地整合各种大型语言模型 (LLM),包括开源模型。

    本教程将带你学习如何将开源 LLM 整合到 MetaGPT 中,并利用它们来生成项目输出。

    注意:

    由于开源模型本身的限制,本教程中描述的内容无法保证稳定的代码生成。如果你按照本教程进行实验,意味着你已经了解这一点。同时,我们也在探索如何在开源模型下获得更稳定、更高质量的输出。如果你也对此感兴趣,可以加入我们的 Discord 或微信社区群组。相信随着开源模型的更新,这一目标很快就能实现。

    整合流程

    我们将按照以下步骤介绍本教程:

    1. 模型部署: 使用 LLaMA-Factory、FastChat、ollama 等推理库部署相应的 LLM 模型。
    2. LLM 配置: 配置 MetaGPT 以使用部署的 LLM 模型。
    3. 可选:修复 LLM 输出: 修复开源 LLM 输出,以提高执行成功率。
    4. 运行: 运行 MetaGPT,并观察结果。

    模型部署

    建议使用 OpenAI 兼容的接口进行模型部署。这样,请求和响应可以直接使用 OpenAI SDK 处理,简化了整合过程。以下推理库支持发布 OpenAI 兼容的接口(ollama 除外):

    注意: 默认情况下,你需要有显卡资源进行部署,否则 CPU 推理会比较慢。

    LLaMA-Factory

    安装:

    git clone https://github.com/hiyouga/LLaMA-Factory.git
    conda create -n llama_factory python=3.10
    conda activate llama_factory
    cd LLaMA-Factory
    pip install -r requirements.txt

    部署:

    • 启动源模型:
    python3 src/api_demo.py \
        --model_name_or_path meta-llama/Llama-2-13b-chat-hf \
        --template llama2
    • 加载和合并 LoRA 输出:
    python3 src/api_demo.py \
        --model_name_or_path path_to_llama2_model \
        --template llama2 \
        --finetuning_type lora \
        --checkpoint_dir path_to_checkpoint

    默认情况下,接口访问地址为 http://0.0.0.0:8000/。如果需要修改端口,请进入 src/api_demo.py 文件进行修改。如果需要使用多张显卡启动,请在启动命令前添加 CUDA_VISIBLE_DEVICES=0,1,2 并替换为你的显卡编号。不同的模型支持不同的模板值,可以在 src/llmtuner/data/template.py 文件中找到。

    请求示例:

    curl -X POST http://0.0.0.0:8000/v1/chat/completions -H "content-type:application/json" -d '{
      "messages":[{"role":"user","content":"who are you"}],
      "model": "gpt-3.5-turbo",
      "stream": false,
      "max_tokens": 256
    }'

    默认情况下,请求的模型参数值为 gpt-3.5-turbo,如有必要,请修改它。进入 src/llmtuner/api/app.py 文件的 list_models 方法,并修改为你的自定义值。

    FastChat

    安装:

    pip3 install "fschat[model_worker,webui]"

    部署:

    • 启动控制器:
    python3 -m fastchat.serve.controller
    • 启动源模型工作器:
    python3 -m fastchat.serve.model_worker --model-path lmsys/vicuna-13b-v1.5 --conv-template vicuna_v1.1 --model-names vicuna
    • 启动 OpenAI 兼容接口:
    python3 -m fastchat.serve.openai_api_server --host localhost --port 8000

    如果你需要启动 LoRA 微调模型,需要先进行模型合并。

    请求示例:

    curl -X POST http://0.0.0.0:8000/v1/chat/completions -H "content-type:application/json" -d '{
      "messages":[{"role":"user","content":"who are you"}],
      "model": "gpt-3.5-turbo",
      "stream": false,
      "max_tokens": 256
    }'

    默认情况下,请求的模型参数值为 vicuna,对应于启动 model_worker 时指定的 model-names

    vllm

    安装:

    pip3 install vllm

    部署:

    python3 -m vllm.entrypoints.openai.api_server \
        --model meta-llama/Llama-2-13b-hf \
        --served-model-name llama2-13b

    请求示例:

    curl -X POST http://0.0.0.0:8000/v1/chat/completions -H "content-type:application/json" -d '{
      "messages":[{"role":"user","content":"who are you"}],
      "model": "llama2-13b",
      "stream": false,
      "max_tokens": 256
    }'

    默认情况下,请求的模型参数值为 llama2-13b,对应于启动时指定的 served-model-name

    ollama

    安装:

    curl https://ollama.ai/install.sh | sh

    部署:

    ollama run llama2  # 下载速度很快 (10+MB/s)

    非本地访问:

    ollama 服务默认情况下只能本地访问,即 http://localhost:11434/api/chathttp://127.0.0.1:11434/api/chat。如果你想要支持 http://ip:11434/api/chat,可以按照以下步骤操作:

    service ollama stop
    
    OLLAMA_HOST=0.0.0.0 OLLAMA_ORIGINS=* ollama serve  # 一个终端
    
    ollama run llama2                                  # 另一个终端

    请求示例:

    # 默认情况下是非流式,`stream: true`
    curl -X POST http://localhost:11434/api/chat -d '{
      "model": "llama2",
      "messages": [
        {
          "role": "user",
          "content": "why is the sky blue?"
        }
      ]
     }'

    LLM 配置

    完成模型部署后,需要修改 config/config2.yaml 文件来配置 MetaGPT 使用部署的 LLM 模型。

    OpenAI 兼容接口

    例如 LLaMA-Factory、FastChat、vllm 的 OpenAI 兼容接口:

    llm:
      api_type: 'open_llm'
      base_url: 'http://106.75.10.xxx:8000/v1'
      model: 'llama2-13b'

    base_url 只需要配置到 http://0.0.0.0:8000/v1,其余部分由 OpenAI SDK 自动填充。model 是请求接口参数 model 的实际值。

    ollama API 接口

    例如通过 ollama 部署的模型服务:

    llm:
      api_type: 'ollama'
      base_url: 'http://127.0.0.1:11434/api'
      model: 'llama2'

    base_url 只需要配置到 http://127.0.0.1:11434/api,其余部分由 Ollama LLM 自动填充。model 是请求参数 model 的实际值。

    可选:修复 LLM 输出

    背景:

    本教程主要介绍如何在 MetaGPT 中整合开源模型(以及非 OpenAI 的闭源模型)。由于 LLM 的输出结果与提示词指令格式密切相关,开源模型(以及一些非 OpenAI 的闭源模型)往往非常复杂。它们很难完全按照 MetaGPT 现有角色的指令进行输出,导致输出内容缺失、遗漏和错误。主要表现如下:

    • 目标键无法按照提示词约定的大小写进行输出。
    • 输出的 JSON 纯文本包含缺失或多余的特殊字符,例如 {"a":b"}}, {"a":b"]}, {"a":b" 等等。

    为了解决这些问题,MetaGPT 添加了修复开源 LLM 输出的功能。

    配置:

    llm: ...
    
    repair_llm_output: true

    开启此功能后,执行过程中会尝试修复上述情况。但目前该功能无法保证完全修复,仍存在一些未覆盖的情况(不同的开源模型有不同的情况),执行过程可能会中断并退出。如果你对此感兴趣,请提交 PR 并附上相应的模型描述、测试日志和单元测试用例。

    开启此功能后,LLM 输出(MetaGPT 中软件公司中的 ProductManagerArchitect 角色)将会被修复。日志中会出现 repair_ 关键字,你可以关注它。

    运行

    完成上述步骤后,你就可以正式开始使用了。

    metagpt "write a snake game"

    扩展

    MetaGPT 本身是一个多智能体框架,并不局限于软件项目生成。你也可以结合整合的开源模型,构建相应的智能体,用于自己的应用场景。开始你的智能体之旅吧!

  • MetaGPT 人机协作:让 AI 与人类并肩作战

    在之前的教程中,我们学习了如何创建和使用智能体以及工具。但有时候,我们希望在 AI 系统中引入人类的参与,例如在项目中进行质量保证、在关键决策中提供指导或在游戏中进行角色扮演。这就是 MetaGPT 人机协作功能发挥作用的地方。

    本教程将带你学习如何将人类引入到 MetaGPT 的 AI 系统中,实现人机协作。

    人机交互

    MetaGPT 允许你在 LLM 驱动的智能体和人类之间进行交互。

    示例:

    我们以之前的多智能体教程为例。原本,SimpleReviewer 角色由 LLM 扮演。假设我们想要对审查过程有更多控制权,可以自己扮演 SimpleReviewer 角色。

    只需要在初始化 SimpleReviewer 时设置 is_human=True 即可。代码如下:

    team.hire(
        [
            SimpleCoder(),
            SimpleTester(),
            # SimpleReviewer(),  # 原代码
            SimpleReviewer(is_human=True),  # 修改后的代码
        ]
    )

    现在,你将以人类的身份扮演 SimpleReviewer,与两个 LLM 驱动的智能体 SimpleCoderSimpleTester 进行交互。你可以对 SimpleTester 生成的单元测试进行评论,例如要求增加覆盖率或边缘情况测试。你的反馈将被发送回 SimpleTester,以便它编写新版本的测试用例。

    交互方式

    每次轮到人类进行响应时,运行过程将会暂停,等待你的输入。只需输入你想要的内容,你的消息就会被发送到智能体。

    限制:

    • 目前,交互是通过终端输入进行的,对于多行或结构化的文本输入不太方便。
    • 用户必须遵守提示词的内容或格式要求,以便在人类输入后,逻辑能够正常运行。

    总结

    本教程展示了如何将人类引入到 MetaGPT 的 AI 系统中,实现人机协作。通过人机协作,你可以更好地控制 AI 系统,并发挥人类的优势,例如创造力、判断力等等。

    更多学习资源

  • MetaGPT 工具:让你的 AI 智能体拥有“外挂”

    在之前的教程中,我们学习了如何使用记忆来提升智能体的能力。但有时候,智能体需要与外部环境进行交互,例如获取信息、执行操作等等。这就是 MetaGPT 工具发挥作用的地方。

    MetaGPT 工具可以帮助你的智能体扩展能力,就像给它安装了“外挂”一样。本教程将带你学习如何创建和使用 MetaGPT 工具。

    创建工具

    在 MetaGPT 中,创建工具非常简单,只需在 metagpt/tools/libs 目录中创建自己的函数或类即可。

    步骤:

    1. 创建函数或类: 编写函数或类,用于实现与外部环境的交互。
    2. 添加 Google 风格的文档字符串: 为每个函数或类添加文档字符串,用于描述其用途、输入参数和预期输出。
    3. 使用 @register_tool 装饰器: 使用 @register_tool 装饰器将函数或类注册到工具注册表中。

    示例:

    假设你想创建一个计算阶乘的工具,名为 calculate_factorial。你可以创建一个名为 calculate_factorial.py 的文件,并在其中添加以下代码:

    # metagpt/tools/libs/calculate_factorial.py
    import math
    from metagpt.tools.tool_registry import register_tool
    
    # 使用装饰器注册工具
    @register_tool()
    def calculate_factorial(n):
        """
        计算一个非负整数的阶乘。
        """
        if n < 0:
            raise ValueError("输入必须是非负整数")
        return math.factorial(n)

    使用工具

    创建工具后,你可以使用 DataInterpreter 角色来使用它。

    示例:

    假设你想要使用 calculate_factorial 工具来计算 5 的阶乘。你可以创建一个名为 main.py 的文件,并在其中添加以下代码:

    # main.py
    import asyncio
    from metagpt.roles.di.data_interpreter import DataInterpreter
    from metagpt.tools.libs import calculate_factorial
    
    async def main(requirement: str):
       role = DataInterpreter(tools=["calculate_factorial"])  # 集成工具
       await role.run(requirement)
    
    if __name__ == "__main__":
       requirement = "请计算 5 的阶乘。"
       asyncio.run(main(requirement))

    这段代码首先导入必要的模块,然后定义一个 main 函数。在 main 函数中,我们创建了一个 DataInterpreter 角色,并使用 tools 参数指定了要使用的工具。最后,我们使用 role.run() 方法运行角色,并打印输出结果。

    工具定制

    MetaGPT 支持多种工具定制方式,例如:

    • 从函数定制工具: 如上面的 calculate_factorial 示例。
    • 从类定制工具: 你可以创建一个类,并使用 @register_tool 装饰器注册它。

    示例:

    假设你想创建一个名为 Calculator 的类,用于执行基本的算术运算和计算阶乘。你可以创建一个名为 calculator.py 的文件,并在其中添加以下代码:

    # metagpt/tools/libs/calculator.py
    import math
    from metagpt.tools.tool_registry import register_tool
    
    # 使用装饰器注册工具,并指定标签和包含的函数
    @register_tool(tags=["math"], include_functions=["__init__", "add", "subtract", "multiply", "divide", "factorial"])
    class Calculator:
       """
       一个简单的计算器工具,可以执行基本的算术运算和计算阶乘。
       """
    
       @staticmethod
       def add(a, b):
           """
           计算两个数字的和。
           """
           return a + b
    
       @staticmethod
       def subtract(a, b):
           """
           计算两个数字的差。
           """
           return a - b
    
       @staticmethod
       def multiply(a, b):
           """
           计算两个数字的积。
           """
           return a * b
    
       @staticmethod
       def divide(a, b):
           """
           计算两个数字的商。
           """
           if b == 0:
               return "错误:除数不能为零"
           else:
               return a / b
    
       @staticmethod
       def factorial(n):
           """
           计算一个非负整数的阶乘。
           """
           if n < 0:
               raise ValueError("输入必须是非负整数")
           return math.factorial(n)

    总结

    本教程展示了如何使用 MetaGPT 创建和使用工具。通过创建工具,你可以扩展智能体的能力,使其能够执行更复杂的任务。

    更多学习资源

  • MetaGPT 中的记忆:让你的 AI 智能体拥有记忆力

    在之前的教程中,我们已经了解了智能体和多智能体系统。但一个真正强大的 AI 智能体,还需要拥有记忆能力。记忆可以帮助智能体积累经验,并根据过去的经验进行决策和行动。

    本教程将带你了解 MetaGPT 中的记忆功能,以及如何使用它来提升你的 AI 智能体的能力。

    MetaGPT 中的记忆

    在 MetaGPT 中,Memory 类是智能体记忆的抽象表示。当一个角色被初始化时,它会获得一个 Memory 对象,用于存储它观察到的所有消息。这些消息会被保存在一个列表中,方便以后检索。

    检索记忆

    当你需要使用记忆时,例如将记忆作为 LLM 的上下文,可以使用 self.get_memories() 方法。该方法的定义如下:

    def get_memories(self, k=0) -> list[Message]:
        """A wrapper to return the most recent k memories of this role, return all when k=0"""
        return self.rc.memory.get(k=k)

    该方法接受一个可选参数 k,用于指定要检索的最近记忆数量。如果 k 为 0,则返回所有记忆。

    例如,在之前的多智能体教程中,我们使用 get_memories() 方法将所有记忆作为上下文提供给测试者。这样,如果审查者提供了反馈,测试者可以参考之前的版本修改测试用例。代码片段如下:

    async def _act(self) -> Message:
        logger.info(f"{self._setting}: ready to {self.rc.todo}")
        todo = self.rc.todo
    
        # context = self.get_memories(k=1)[0].content  # 使用最近的记忆作为上下文
        context = self.get_memories()  # 使用所有记忆作为上下文
    
        code_text = await todo.run(context, k=5)  # 指定参数
    
        msg = Message(content=code_text, role=self.profile, cause_by=todo)
    
        return msg

    添加记忆

    要添加记忆,可以使用 self.rc.memory.add(msg) 方法,其中 msg 必须是 Message 类的实例。

    建议在定义 _act 方法时,将动作输出的消息添加到角色的记忆中。角色通常需要记住它之前说过的话或做过的事,才能采取下一步行动。

    下一步

    本教程介绍了 MetaGPT 中的“短期记忆”概念。记忆的检索是基于简单的最近性原则。然而,还有许多其他类型的记忆,以及各种各样的记忆生成和检索技术。你可以参考 Memory 教程,了解如何使用记忆来真正提升你的智能体的性能。

  • MetaGPT 多智能体 101:打造你的第一个 AI 团队

    在上一章中,我们学习了如何创建一个单个智能体。虽然单个智能体在许多情况下已经足够,但对于更复杂的任务,往往需要协作和团队合作。这就是多智能体系统发挥作用的地方。MetaGPT 的核心优势在于它能够轻松灵活地开发多个智能体组成的团队。在 MetaGPT 框架下,只需编写少量代码,就能实现智能体之间的交互。

    通过本教程,你将学会:

    • 理解智能体之间的交互方式
    • 开发你的第一个 AI 团队
    • 运行软件创业示例

    开发你的第一个 AI 团队

    让我们以软件创业为例,想象一下,你需要一个团队来开发一个 CLI 版本的 Flappy Bird 游戏:

    metagpt "write a cli flappy bird game"

    这个简单的命令就可以启动 MetaGPT,并让它自动组建一个 AI 团队来完成这个任务。

    1. 定义角色和动作

    与单个智能体类似,我们需要定义每个角色以及它们能够执行的动作。

    • SimpleCoder: 接受用户指令,编写主要代码。
    • SimpleTester: 接受 SimpleCoder 生成的代码,编写测试用例。
    • SimpleReviewer: 接受 SimpleTester 生成的测试用例,审查其覆盖率和质量。

    每个角色对应一个动作:

    • SimpleWriteCode: 接受用户指令,生成 Python 代码。
    • SimpleWriteTest: 接受代码,生成测试用例。
    • SimpleWriteReview: 审查测试用例,并提供评论。

    2. 定义角色

    在 MetaGPT 中,定义一个角色通常只需要几行代码。

    SimpleCoder:

    class SimpleCoder(Role):
        name: str = "Alice"
        profile: str = "SimpleCoder"
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self._watch([UserRequirement])  # 监听用户指令
            self.set_actions([SimpleWriteCode])

    SimpleTester:

    class SimpleTester(Role):
        name: str = "Bob"
        profile: str = "SimpleTester"
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.set_actions([SimpleWriteTest])
            self._watch([SimpleWriteCode])  # 监听 SimpleCoder 生成的代码
            # self._watch([SimpleWriteCode, SimpleWriteReview])  # 可以尝试监听更多信息
    
        async def _act(self) -> Message:
            logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
            todo = self.rc.todo
    
            # context = self.get_memories(k=1)[0].content  # 使用最近的记忆作为上下文
            context = self.get_memories()  # 使用所有记忆作为上下文
    
            code_text = await todo.run(context, k=5)  # 指定参数
            msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
    
            return msg

    SimpleReviewer:

    class SimpleReviewer(Role):
        name: str = "Charlie"
        profile: str = "SimpleReviewer"
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.set_actions([SimpleWriteReview])
            self._watch([SimpleWriteTest])  # 监听 SimpleTester 生成的测试用例

    3. 创建团队

    现在,我们已经定义了三个角色,可以将它们组合成一个团队:

    import asyncio
    import typer
    from metagpt.logs import logger
    from metagpt.team import Team
    app = typer.Typer()
    
    @app.command()
    def main(
        idea: str = typer.Argument(..., help="write a function that calculates the product of a list"),
        investment: float = typer.Option(default=3.0, help="Dollar amount to invest in the AI company."),
        n_round: int = typer.Option(default=5, help="Number of rounds for the simulation."),
    ):
        logger.info(idea)
    
        team = Team()
        team.hire(
            [
                SimpleCoder(),
                SimpleTester(),
                SimpleReviewer(),
            ]
        )
    
        team.invest(investment=investment)
        team.run_project(idea)
        asyncio.run(team.run(n_round=n_round))
    
    if __name__ == '__main__':
        app()

    这段代码首先定义了一个 main 函数,并创建一个 Team 对象。然后,我们使用 team.hire() 方法雇佣了三个角色。最后,我们使用 team.run() 方法运行团队,并打印输出结果。

    运行团队

    现在,你可以运行这段代码,并观察团队之间的协作:

    python3 examples/build_customized_multi_agents.py --idea "write a function that calculates the product of a list"

    总结

    本教程展示了如何使用 MetaGPT 创建一个简单的 AI 团队,并演示了如何定义角色和动作,以及如何运行团队。你可以在此基础上进一步扩展你的团队,使其能够执行更复杂的任务。

    更多学习资源

  • MetaGPT 智能体 101:打造你的第一个 AI 智能体

    本教程将带你从零开始,一步步打造你的第一个 MetaGPT 智能体。通过本教程,你将学会:

    • 使用现成的智能体
    • 开发一个可以执行一个或多个动作的智能体

    使用现成的智能体

    MetaGPT 提供了许多现成的智能体,你可以直接导入并使用。例如,以下代码展示了如何使用 ProductManager 智能体来编写一个产品需求文档 (PRD):

    import asyncio
    
    from metagpt.context import Context
    from metagpt.roles.product_manager import ProductManager
    from metagpt.logs import logger
    
    async def main():
        msg = "Write a PRD for a snake game"
        context = Context()  # 创建会话上下文对象
        role = ProductManager(context=context)  # 初始化智能体
        while msg:
            msg = await role.run(msg)  # 运行智能体
            logger.info(str(msg))
    
    if __name__ == '__main__':
        asyncio.run(main())

    这段代码首先导入必要的模块,然后定义一个 main 函数。在 main 函数中,我们创建了一个会话上下文对象 context,并使用 ProductManager 类初始化一个智能体 role。最后,我们使用 role.run() 方法运行智能体,并打印输出结果。

    开发你的第一个智能体

    从实际应用的角度来看,一个有用的智能体需要能够执行某些动作。MetaGPT 提供了高度灵活的方式来定义自己的动作和智能体。

    1. 定义动作

    在 MetaGPT 中,Action 类是动作的抽象表示。你可以使用 LLM 来增强 Action,只需调用 self._aask 函数即可。

    例如,我们想创建一个名为 SimpleWriteCode 的动作,用于根据自然语言描述编写 Python 代码:

    import re
    from metagpt.actions import Action
    
    class SimpleWriteCode(Action):
        PROMPT_TEMPLATE: str = """
        Write a python function that can {instruction} and provide two runnnable test cases.
        Return ```python your_code_here ``` with NO other texts,
        your code:
        """
    
        name: str = "SimpleWriteCode"
    
        async def run(self, instruction: str):
            prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)
            rsp = await self._aask(prompt)
            code_text = SimpleWriteCode.parse_code(rsp)
            return code_text
    
        @staticmethod
        def parse_code(rsp):
            pattern = r"```python(.*)```"
            match = re.search(pattern, rsp, re.DOTALL)
            code_text = match.group(1) if match else rsp
            return code_text

    这段代码定义了一个名为 SimpleWriteCode 的类,它继承自 Action 类。该类包含一个 PROMPT_TEMPLATE 属性,用于定义提示词模板。run 方法接受一个自然语言描述 instruction,并使用提示词模板生成一个提示词,然后调用 _aask 函数向 LLM 发送请求,并返回代码文本。

    2. 定义角色

    在 MetaGPT 中,Role 类是智能体的抽象表示。一个角色可以执行某些动作,拥有记忆,并根据不同的策略进行思考和行动。

    例如,我们想创建一个名为 SimpleCoder 的角色,它可以使用 SimpleWriteCode 动作来编写代码:

    from metagpt.roles import Role
    
    class SimpleCoder(Role):
        name: str = "Alice"
        profile: str = "SimpleCoder"
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.set_actions([SimpleWriteCode])
    
        async def _act(self) -> Message:
            logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
            todo = self.rc.todo  # 获取当前动作
    
            msg = self.get_memories(k=1)[0]  # 获取最近一条消息
            code_text = await todo.run(msg.content)  # 执行动作
            msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
    
            return msg

    这段代码定义了一个名为 SimpleCoder 的类,它继承自 Role 类。该类包含一个 name 属性和一个 profile 属性,用于定义角色的名称和描述。__init__ 方法用于初始化角色,并使用 set_actions 方法添加 SimpleWriteCode 动作。_act 方法定义了角色的行动逻辑,它会获取最近一条消息,并使用当前动作执行代码编写任务。

    3. 运行你的角色

    现在,你可以初始化你的角色并运行它:

    import asyncio
    
    from metagpt.context import Context
    
    async def main():
        msg = "write a function that calculates the product of a list"
        context = Context()
        role = SimpleCoder(context=context)
        logger.info(msg)
        result = await role.run(msg)
        logger.info(result)
    
    asyncio.run(main())

    这段代码首先定义一个 main 函数,并创建一个会话上下文对象 context。然后,我们使用 SimpleCoder 类初始化一个角色 role。最后,我们使用 role.run() 方法运行角色,并打印输出结果。

    智能体拥有多个动作

    一个智能体可以拥有多个动作,并根据不同的策略来选择执行哪个动作。例如,我们想创建一个名为 RunnableCoder 的角色,它可以编写代码并立即执行:

    1. 定义动作

    除了 SimpleWriteCode 动作,我们还需要定义一个名为 SimpleRunCode 的动作,用于执行代码:

    class SimpleRunCode(Action):
        name: str = "SimpleRunCode"
    
        async def run(self, code_text: str):
            result = subprocess.run(["python3", "-c", code_text], capture_output=True, text=True)
            code_result = result.stdout
            logger.info(f"{code_result=}")
            return code_result

    2. 定义角色

    我们修改 RunnableCoder 角色,使其拥有 SimpleWriteCodeSimpleRunCode 两个动作:

    class RunnableCoder(Role):
        name: str = "Alice"
        profile: str = "RunnableCoder"
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.set_actions([SimpleWriteCode, SimpleRunCode])
            self._set_react_mode(react_mode="by_order")
    
        async def _act(self) -> Message:
            logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
            todo = self.rc.todo  # 获取当前动作
    
            msg = self.get_memories(k=1)[0]  # 获取最近一条消息
            result = await todo.run(msg.content)  # 执行动作
    
            msg = Message(content=result, role=self.profile, cause_by=type(todo))
            self.rc.memory.add(msg)
            return msg

    这段代码中,我们使用 set_actions 方法添加了两个动作,并使用 _set_react_mode 方法设置了动作执行策略为 by_order,表示按照动作定义的顺序执行。

    3. 运行你的角色

    现在,你可以初始化 RunnableCoder 角色并运行它:

    import asyncio
    
    from metagpt.context import Context
    
    async def main():
        msg = "write a function that calculates the product of a list"
        context = Context()
        role = RunnableCoder(context=context)
        logger.info(msg)
        result = await role.run(msg)
        logger.info(result)
    
    asyncio.run(main)

    这段代码与之前类似,只是使用了 RunnableCoder 角色。

    总结

    本教程展示了如何使用 MetaGPT 创建一个简单的智能体,并演示了如何定义动作和角色,以及如何运行智能体。你可以在此基础上进一步扩展你的智能体,使其能够执行更复杂的任务。

    更多学习资源

  • MetaGPT 的核心概念:智能体与多智能体系统

    MetaGPT 框架的核心概念是 智能体 (Agent)多智能体系统 (MultiAgent System)。理解这两个概念是使用 MetaGPT 构建复杂 AI 应用的关键。

    智能体 (Agent)

    智能体可以被理解为一个在环境中运行的数字生物,它拥有以下几个关键组成部分:

    • 大型语言模型 (LLM):LLM 是智能体的“大脑”,它负责处理信息、学习、决策和执行行动。
    • 观察 (Observation):智能体的“感官”,通过观察环境来获取信息。例如,它可以接收来自其他智能体的消息、来自监控摄像头的图像数据或来自客服录音的音频信息。
    • 思考 (Thought):智能体的“思维”,通过分析观察结果、调用记忆和考虑可能的行动来进行决策。
    • 行动 (Action):智能体的“行为”,根据思考结果采取行动,例如使用 LLM 生成代码、执行预定义的操作(如读取本地文件)或使用工具(如网页搜索、计算器等)。
    • 记忆 (Memory):智能体的“记忆”,存储过去的经验,帮助它学习和调整未来的行动。

    多智能体系统 (MultiAgent System)

    多智能体系统可以被看作是一个由多个智能体组成的社会,它包含以下几个关键组成部分:

    • 智能体 (Agents):每个智能体都拥有自己的 LLM、观察、思考、行动和记忆。
    • 环境 (Environment):智能体之间交互的共享空间。智能体可以从环境中获取信息,并将行动结果发布到环境中供其他智能体使用。
    • 标准操作流程 (SOP):定义智能体行为和交互的规范,确保系统有序高效地运行。
    • 通信 (Communication):智能体之间信息交换的方式,用于协作、谈判和竞争。
    • 经济 (Economy):多智能体系统中资源分配和任务优先级的机制。

    一个简单的例子

    想象一下,三个智能体 Alice、Bob 和 Charlie 在一个环境中相互交互。他们可以向环境发布消息或行动结果,其他智能体可以观察这些信息。

    以 Charlie 为例,它内部包含 LLM、观察、思考、行动等组件。它可以观察来自 Alice 的相关文档和来自 Bob 的需求,回忆相关的记忆,思考如何编写代码,并执行代码编写行动,最后将结果发布到环境中。

    Charlie 将行动结果发布到环境中,Bob 观察到结果并给予赞赏。

    总结

    MetaGPT 提供了一个框架,可以帮助你创建智能体并定义它们之间的交互关系。通过理解智能体和多智能体系统的概念,你可以更好地理解 MetaGPT 的工作原理,并构建更加复杂和智能的 AI 应用。

    进一步学习

  • MetaGPT 快速上手指南

    MetaGPT 是一个基于大型语言模型 (LLM) 的多智能体协作框架,它能够将人类的程序化知识融入到 AI 软件开发中,提高代码生成效率和质量。本文将带您快速上手 MetaGPT,体验用一句话需求生成软件项目的便捷和高效。

    安装

    首先,我们需要安装 MetaGPT:

    !pip install metagpt==0.6.0

    设置

    安装完成后,我们需要设置 OpenAI API 密钥和模型:

    import os
    os.environ["OPENAI_API_KEY"] = "sk-..."
    os.environ["OPENAI_API_MODEL"] = "gpt-4-1106-preview"

    请将 sk-... 替换为您的 OpenAI API 密钥。

    用一句话需求生成软件项目

    MetaGPT 的强大之处在于,您只需输入一句话的需求,它就能自动生成一个完整的软件项目,包括需求文档、代码、测试用例等等。

    以下我们将创建一个团队,并使用 MetaGPT 生成一个简单的 2048 游戏:

    1. 导入角色: 首先,我们需要导入 MetaGPT 提供的预定义角色:
    import asyncio
    
    from metagpt.roles import (
        Architect,
        Engineer,
        ProductManager,
        ProjectManager,
    )
    from metagpt.team import Team
    1. 组建团队: 创建一个团队,并招募产品经理、架构师、项目经理和工程师:
    async def startup(idea: str):
        company = Team()
        company.hire(
            [
                ProductManager(),
                Architect(),
                ProjectManager(),
                Engineer(),
            ]
        )
        company.invest(investment=3.0)
        company.run_project(idea=idea)
    
        await company.run(n_round=5)
    1. 运行项目: 输入您的需求,并运行项目:
    history = await startup(idea="write a 2048 game")

    MetaGPT 会自动开始工作,并生成以下内容:

    • 需求文档: 包括产品目标、用户故事、竞争分析、需求分析、需求池、UI 设计草稿等。
    • 系统设计: 包括文件列表、数据结构、接口定义、程序调用流程等。
    • 代码: 包括 constants.py、game.py、ui.py、main.py 等文件。
    • 测试用例: 包括测试代码。

    项目结果

    运行结束后,您可以在 workspace 目录下找到生成的项目代码和文档。

    MetaGPT 的快速上手指南就到这里,您已经体验了用一句话需求生成软件项目的便捷和高效。MetaGPT 的强大功能和灵活的扩展性,让它成为未来 AI 软件开发的重要工具。

    参考文献

  • MetaGPT:赋能多智能体协作的元编程框架

    近年来,基于大型语言模型 (LLM) 的多智能体系统在自动问题解决方面取得了显著进展。现有的 LLM 多智能体系统已能解决简单的对话任务,但对于更复杂的任务,由于 LLM 简单的链式连接导致的级联幻觉问题,导致逻辑不一致,难以找到有效的解决方案。

    为了解决这个问题,我们提出了 MetaGPT,一个创新的元编程框架,将高效的人类工作流程融入到基于 LLM 的多智能体协作中。MetaGPT 将标准操作流程 (SOP) 编码到提示序列中,从而实现更简化的工作流程,让具有类似人类领域专业知识的代理能够验证中间结果,减少错误。MetaGPT 利用流水线模式,将不同的角色分配给不同的代理,有效地将复杂的任务分解为多个代理协同完成的子任务。

    在协作软件工程基准测试中,MetaGPT 生成的解决方案比以前的基于聊天的多智能体系统更加连贯。我们的项目可以在 https://github.com/geekan/MetaGPT 找到。

    MetaGPT 的核心优势

    • 将 SOP 融入 LLM 多智能体协作: MetaGPT 借鉴了人类在各个领域中积累的 SOP,将这些流程标准化,并将其转化为 LLM 代理可以理解和执行的指令。这使得 LLM 代理能够像人类团队一样,遵循明确的流程,进行有效协作。
    • 角色分工与协作: MetaGPT 将 LLM 代理分配不同的角色,例如产品经理、架构师、工程师等,每个角色都拥有特定的技能和职责。这些代理之间通过结构化的信息传递进行协作,确保每个环节的质量和效率。
    • 可执行的反馈机制: MetaGPT 引入了可执行的反馈机制,使 LLM 代理能够在代码生成过程中实时验证和调试代码,从而提高代码质量。

    MetaGPT 的实验结果

    我们在 HumanEval 和 MBPP 等公开基准测试上,以及我们自己构建的更具挑战性的 SoftwareDev 基准测试上,对 MetaGPT 进行了评估。结果表明,MetaGPT 在代码生成方面取得了新的最先进水平 (SoTA),在 HumanEval 和 MBPP 上的 Pass@1 分别达到了 85.9% 和 87.7%。

    与 AutoGPT、LangChain、AgentVerse 和 ChatDev 等其他流行的复杂软件项目框架相比,MetaGPT 在处理更高水平的软件复杂性和提供更广泛的功能方面也表现出色。值得注意的是,在我们的实验评估中,MetaGPT 达到了 100% 的任务完成率,证明了我们设计方案的鲁棒性和效率 (时间和代币成本)。

    未来展望

    MetaGPT 的成功,为我们展示了将人类工作流程融入 LLM 多智能体系统中的巨大潜力。未来,我们将继续探索以下方向:

    • 自改进机制: 让 MetaGPT 能够从过去的项目经验中学习,不断提升自身的性能和效率。
    • 多智能体经济: 构建一个更加灵活的协作环境,让 LLM 代理能够根据需求动态调整工作流程和角色分配。

    MetaGPT 的出现,标志着 AI 协作软件开发的全新时代。它将改变传统的软件开发模式,为我们带来更加高效、便捷的软件开发体验。

    参考文献

  • MetaGPT:借鉴人类协作模式,赋能多智能体软件工程

    MetaGPT,这个由中美高校研究人员共同研发的 LLM 元编程框架,正试图通过借鉴人类的程序化知识,来提升多智能体系统的协作能力,从而降低错误率,增强鲁棒性,并最终实现复杂任务的软件解决方案。

    MetaGPT 的核心:标准操作流程 (SOP)

    MetaGPT 的核心思想是将标准操作流程 (SOP) 编码到提示中,从而模拟协作任务所需的有效程序化知识。研究人员指出,敏捷宣言以及其他在团队中分配任务和责任的方法,都是软件领域中 SOP 的例子,包括对所需输出的定义,例如高质量的需求文档、设计工件、流程图和界面规范。

    MetaGPT 利用 SOP 来组织多智能体的协作,提升协作效率。它将代理分为产品经理、架构师、项目经理和工程师等角色,每个角色都拥有特定的行动规范,并能够在共享环境中互相观察和获取相关信息。这比通过对话被动接收数据更有效率。

    MetaGPT 的架构

    MetaGPT 的架构主要分为两层:

    • 基础组件层: 允许代理执行操作。
    • 协作层: 通过知识共享和工作流程封装,促进代理协调。

    MetaGPT 的优势

    MetaGPT 团队声称,与 AutoGPT、LangChain 和 AgentVerse 等现有框架相比,MetaGPT 可以处理更高水平的软件复杂性,并拥有 100% 的任务完成率。

    MetaGPT 的局限性

    MetaGPT 并非完美的 AI 协作系统,仍然需要克服 LLM 系统的幻觉倾向,例如,MetaGPT 可能引用不存在的资源文件,或调用未定义或未导入的类或变量。

    未来展望

    MetaGPT 的出现,意味着 AI 协作软件开发的全新时代。它将改变传统的软件开发模式,为我们带来更加高效、便捷的软件开发体验。

    参考文献

  • MetaGPT:狼人杀游戏中的多智能体协作

    狼人杀,这个风靡全球的策略游戏,如今也迎来了 AI 的挑战!MetaGPT,这个多智能体框架,成功地将狼人杀游戏搬上了 AI 舞台,让多个 GPT 模型扮演不同的角色,进行一场场精彩绝伦的“狼人杀”对决。

    MetaGPT 实现狼人杀游戏的关键

    MetaGPT 的设计理念,使其成为构建狼人杀游戏的理想平台:

    • 精细化沟通: 游戏中,玩家需要进行复杂的交流,MetaGPT 的“环境”和“消息”抽象,以及代理的“发布消息”和“观察消息”功能,完美地实现了玩家之间信息传递和互动。
    • 智能代理: MetaGPT 的“角色”抽象,可以将游戏中的每个角色定义为一个独立的代理,并赋予他们不同的技能和行为方式。
    • 多功能代理: 每个代理可以拥有“思考”、“行动”和“记忆”等功能,并通过“反思”和“经验学习”机制,不断提升自己的游戏策略。

    狼人杀游戏中的 AI 行为

    MetaGPT 中的 AI 代理们展现出了令人惊叹的逻辑和策略能力:

    • 合作与勾结: 警卫会保护预言家,狼人会互相支持,互相掩护。
    • 对抗与质疑: 真预言家会站出来揭露假预言家,狼人会试图混淆视听。
    • 背叛与权衡: 狼人会根据形势判断,选择放弃同伴,或选择隐忍待机。
    • 复杂推理: 玩家会根据投票、发言和游戏状态,推断其他玩家的身份和意图。

    MetaGPT 狼人杀游戏的未来

    MetaGPT 的狼人杀游戏还在不断完善,未来将拥有更多功能:

    • 更丰富的角色: 将加入更多经典的狼人杀角色,例如猎人、女巫、白痴等等。
    • 更强大的策略: 通过更复杂的算法和训练数据,AI 代理将拥有更强大的策略和推理能力。
    • 更真实的体验: 将加入更多细节和互动,让游戏体验更加真实和有趣。

    MetaGPT 的狼人杀游戏,不仅展现了 AI 在策略游戏领域的能力,也为我们打开了通往未来游戏的新大门。在未来,AI 将与人类玩家并肩作战,共同体验更丰富、更精彩的游戏世界。

    参考文献

  • MetaGPT:AI 赋能的未来工作力

    21 世纪的工作场所正经历着翻天覆地的变化,而人工智能 (AI) 的快速发展,特别是多智能体系统和大型语言模型 (LLM) 的兴起,正在重塑任务执行、协作和决策的模式。

    从医疗保健到金融,AI 应用已无处不在。像 GPT 这样的多智能体系统和 LLM 为我们提供了从决策和问题解决到任务自动化的各种解决方案。这些技术的出现,特别是多智能体系统,使协作解决问题和提高生产力成为可能。它们的影响遍及各个行业,推动着运营模式和商业战略的深刻转变。

    麦肯锡全球研究院的一项研究表明,到 2030 年,AI,特别是多智能体系统和大型语言模型 (LLM),将创造高达 13 万亿美元的全球经济活动。另一项针对全球企业的调查显示,87% 的受访者报告称 AI 投资有所增加。这并不令人意外。AI 能够吸收和分析海量数据,从而促进明智的决策,无论是预测市场趋势还是优化运营工作流程。AI 在自动化任务方面发挥的作用,将人类从以前的手动工作中解放出来,让他们能够承担更具战略性的角色,从而促进效率和创新。

    MetaGPT:多智能体框架

    MetaGPT 代表 Generative Pretrained Transformers,是一个基于 LLM 的多智能体框架。它只需要一行输入,就能生成 API、用户故事、数据结构、竞争分析等等。它可以充当产品经理、软件工程师和架构师,本质上就像一个拥有明确标准操作流程 (SOP) 的完整软件公司。

    MetaGPT 的设计利用了高质量、多样化、结构化的文档和设计生成,使其成为解决复杂问题的有用工具。它的架构包含两个主要层:

    • 基础组件层: 此层提供了单个代理操作的基本构建块,包括:
      • 用于共享通信和工作区的环境。
      • 定义特定领域工作流程和技能的角色。
      • 提供实用程序和服务的工具。
      • 管理子任务的操作。
    • 协作层: 建立在基础组件之上,此层使用各种代理来协作解决复杂问题。它将任务分解成更小的组件,将它们分配给合适的代理,并确保遵循指南。此层还促进代理之间的数据共享,创建共享的知识库。

    MetaGPT 的优势

    MetaGPT 为企业和组织提供了许多优势,包括:

    • 自动化: 它简化了软件开发流程,使开发人员能够专注于战略性和创造性的工作。
    • 整合人类 SOP: MetaGPT 不仅仅是复制标准操作流程;它将核心逻辑和基本原理内化,以确保 AI 驱动的流程满足人类制定的标准。
    • 创意程序生成: 用户可以使用最少的命令生成功能齐全的应用程序。
    • 多个 AI 代理: MetaGPT 利用多个 GPT,每个 GPT 都经过训练可以执行特定任务。
    • 性能增强: MetaGPT 通过细致的研究和现实世界的测试,可以确保准确性、速度和适应性。该框架可以分析现有程序,引入新功能或消除冗余代码。
    • 促进沟通: MetaGPT 促进团队成员之间更好的协作和沟通。

    MetaGPT 的局限性

    尽管 MetaGPT 潜力巨大,但它也有一些局限性:

    • 它仍在开发中。
    • 它可能不适合高度复杂的项目。
    • 它的能力受限于其训练数据,需要频繁更新才能保持准确性。

    结论

    AI 在工作场所的旅程不仅仅关乎算法和数据。这是一个关于人类进步的故事,关于如何充分利用两者的优势,以及如何创造一个技术服务、增强和提升人类潜力的未来。当我们拥抱像 MetaGPT 这样的技术并展望未来时,我们不仅仅见证了一场技术革命;我们正在积极参与塑造未来工作、社会和人类。

    然而,将 LLM 与多智能体系统集成并非没有挑战。值得注意的行业报告强调了诸如模型幻觉之类的问题,即 LLM 生成非事实或上下文不准确的信息。还有一些关于可扩展性和随着模型规模增大而模型性能递减的担忧。

    MetaGPT 的出现,标志着 AI 软件开发的全新时代。它将改变传统的软件开发模式,为我们带来更加高效、便捷的软件开发体验。

  • MetaGPT:让 GPT 像软件公司一样协作工作

    想象一下,你有一个想法,只需要用一句话描述,就能自动生成一个完整的软件项目,包括需求文档、代码、测试用例等等。这听起来像科幻小说,但现在,MetaGPT 正将它变成现实。

    MetaGPT 是一个多智能体框架,它将多个 GPT 模型组合在一起,模拟一个软件公司,协同完成复杂的任务。它就像一个由 AI 驱动的软件开发团队,拥有产品经理、架构师、项目经理、工程师等角色,共同完成从需求分析、设计、开发到测试的全过程。

    MetaGPT 的核心哲学:Code = SOP(Team)

    MetaGPT 的核心哲学是将软件开发流程标准化,并将其具象化为可供 LLM 团队执行的标准操作流程 (SOP)。换句话说,MetaGPT 就像一个“AI 软件开发公司”,它将 GPT 模型赋予不同的角色,并通过精心设计的 SOP 指导它们协同工作。

    ![一个完全由大语言模型角色构成的软件公司][]

    软件公司多角色示意图(正在逐步实现)

    MetaGPT 的强大功能

    MetaGPT 的强大功能体现在以下几个方面:

    • 一键生成软件项目: 你只需要输入一句话的需求,MetaGPT 就能自动生成一个完整的软件项目,包括需求文档、代码、测试用例等等。
    • 多智能体协作: MetaGPT 内部包含多个 GPT 模型,它们扮演不同的角色,协同完成任务,就像一个真正的软件开发团队一样。
    • 标准化流程: MetaGPT 通过精心设计的 SOP 指导 GPT 模型协同工作,确保项目开发的效率和质量。

    如何使用 MetaGPT

    MetaGPT 提供了两种安装方式:

    1. 使用 Pip 安装

    pip install metagpt
    metagpt --init-config  # 创建 ~/.metagpt/config2.yaml,根据您的需求修改它
    metagpt "创建一个 2048 游戏"  # 这将在 ./workspace 创建一个仓库

    2. 使用 Docker 安装

    # 步骤1: 下载metagpt官方镜像并准备好config2.yaml
    docker pull metagpt/metagpt:latest
    mkdir -p /opt/metagpt/{config,workspace}
    docker run --rm metagpt/metagpt:latest cat /app/metagpt/config/config2.yaml > /opt/metagpt/config/config2.yaml
    vim /opt/metagpt/config/config2.yaml # 修改配置文件
    
    # 步骤2: 使用容器运行metagpt演示
    docker run --rm \
        --privileged \
        -v /opt/metagpt/config/config2.yaml:/app/metagpt/config/config2.yaml \
        -v /opt/metagpt/workspace:/app/metagpt/workspace \
        metagpt/metagpt:latest \
        metagpt "Write a cli snake game"

    详细的安装步骤请参考 官方文档

    MetaGPT 的应用场景

    MetaGPT 的应用场景非常广泛,例如:

    • 快速原型开发: MetaGPT 可以帮助你快速构建软件原型,验证想法的可行性。
    • 自动化开发: MetaGPT 可以帮助你自动化部分软件开发工作,例如代码生成、测试用例生成等等。
    • 提高开发效率: MetaGPT 可以帮助你提高软件开发效率,减少开发时间和成本。

    MetaGPT 的未来

    MetaGPT 仍然处于快速发展阶段,未来它将拥有更多功能和更强大的能力,例如:

    • 支持更多编程语言: 目前 MetaGPT 主要支持 Python,未来将支持更多编程语言。
    • 更强大的智能体: MetaGPT 将开发更多类型的智能体,例如数据科学家、设计师等等。
    • 更完善的生态系统: MetaGPT 将构建更完善的生态系统,提供更多工具和资源,方便开发者使用。

    MetaGPT 的出现,标志着 AI 软件开发的全新时代。它将改变传统的软件开发模式,为我们带来更加高效、便捷的软件开发体验。

    参考文献

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 借一步网