0

大模型工具学习探索

 8 months ago
source link: https://www.6aiq.com/article/1703578231219
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

大模型工具学习探索

导读 大模型已经展示出在复杂场景下调动各类工具以解决复杂任务的能力。其深度的语义理解、广泛的世界知识,以及强大的推理和规划能力,共同使得人工智能在模拟人类使用工具的过程中展现出巨大的潜力。在此背景下,基础模型(Foundation Model)的工具学习(Tool Learning)应运而生,该领域的目标是让基础模型能够根据人类的指示和操作来使用工具,以解决特定任务。然而,无论是从理论研究还是实际应用的角度来看,该领域都面临着众多机遇和挑战。本文将介绍清华大学在工具学习领域的一些重要研究成果,并详细介绍其开源的交互式网页搜索中文问答框架 WebCPM、BMTools 和 AgentVerse 工具包。希望这些工作能够帮助读者深化对大模型工具学习领域的理解,同时也欢迎更多的研究者和开发者参与到这些工具包的使用和开发中来,共同推进大模型工具学习范式的发展。

今天的分享会围绕下面四点展开:

  1. 工具学习背景(Background)

  2. 工具学习框架(Framework)

  3. 工具学习应用(Application)

分享嘉宾|秦禹嘉 清华大学 博士生

编辑整理|王帅

内容校对|李瑶

出品社区|DataFun

01工具学习背景 Background

1. 工具与智能(Tools and Intelligence)

工具是人类能力的延伸,旨在提高生产力和效率,以及解决问题。人与动物本质区别在于工具,人可以非常熟练地创造和使用工具。纵观历史,人类一直是工具发明和操作的主要推动者。

GPT-4 等基础模型(Foundation Model)展示了其在理解人类意图、自动化复杂过程、解读多模态信息等方面的巨大潜力。同时也引发了如下问题:人工智能是否可以像人类一样使用工具?

基于大模型、基础模型(Foundation Model),上述问题的回答是 **Yes!**主要原因如下:

  • **强大的语义理解。**大语言模型可以很好地 follow 人的指令。
  • **丰富的世界领域知识。**保证大模型可在各种场景更好地落地应用。
  • **强大的推理和规划能力。**可在复杂场景完成规划任务,将复杂目标分解成多个简单子目标,然后去顺序执行。
  • 执行过程中遇到的问题,可通过推理辅助进行下一步决策。
image-ae61601d79f24834af5368759fd0a422.png-imageStyle

在综述文章 Qin, Yujia, et al. "Tool Learning with Foundation Models." arXiv preprint arXiv:2304.08354 (2023)中,给出了工具学习的定义。**基础模型工具学习,**即基础模型可以跟随人类指令和操作工具,用于解决任务。

image-4e7a9665be304bad9313db09d5163450.png-imageStyle

上图给出了一些工具学习场景的典型应用:

  • **推荐书籍,**若大模型基于 19 年之前的语料进行训练,不了解最新书籍,则会调用搜索引擎,将搜索结果进行答案生成,可弥补时效性不足的问题。
  • 操纵机器人做饭
  • **调用已有工具或模型完成任务,**如调用一些模型进行画画。

2. 工具学习的分类(Categorization of Tool Learning)

现有工具学习主要可以分为两类,工具增强学习(Tool-augmented Learning)和工具导向学习(Tool-oriented Learning),其核心差异在于学习过程中,是通过工具执行来增强基础模型(工具为 AI 服务),还是通过基础模型优化工具的使用(AI 为工具服务)。

  • 工具增强学习(Tool-augmented Learning)
image-6fb0a60c5fe44cb081288fa0a08c67fa.png-imageStyle

工具增强学习利用各种工具的执行结果,增强基础模型性能。在这一范式中,工具执行结果被视为辅助生成高质量输出的外部资源。将工具作为额外资源辅助模型生成,如解决大模型生成过程中的时效性不足或事实性不准确的问题。如用户想了解今天 Twitter 的 Trending,大模型可以调用 Twitter 的 API,得到这些 Trending 后,再进行生成。

  • 工具导向学习(Tool-oriented Learning)
image-8599cdc6127e48f2b291c1b3b356921e.png-imageStyle

工具导向学习,将学习过程重点从增强模型性能转向工具执行本身。这一范式关注开发能够代替人类控制工具并进行序列决策的模型。利用基础模型丰富的世界知识和复杂推理与规划的能力,让模型管理工具,充当整个工具智能的大脑,使其可代替人类高效执行一系列的序列决策。

如人类让大模型到 Twitter 上发一条推特,大模型会先规划,将目标分解为多个子目标,如打开浏览器,登录推特,发送推特。每个子目标的完成可能会去调用 API,逐步完成所有子目标,直到完成最终的目标。

02框架 Framework

1. 工具学习框架

image-070f3ef3693b47c6b9f27f7d739efcbf.png-imageStyle

一个通用的工具学习框架,类似强化学习 MDP 的架构,包含人类用户角色和四个关键组成部分:工具集、控制器、感知器和环境。

  • 工具集(Tool Set):具备不同功能的、可供模型使用的各种工具。从交互接口的视角可以分为三类:基于物理交互的工具、基于 GUI 交互的工具、基于程序交互的工具。
  • 控制器(Controller):提供灵活的规划以满足用户的需求。通常使用基础模型建模,负责接收用户的指令,并根据这些指令制定可执行的计划并调用工具执行。
  • 感知器(Perceiver):负责接收来自环境和用户的反馈信息,并将其汇总给控制器。
  • 环境(Environment):模型或工具实施所处的场景,包括物理环境和虚拟环境等。

工具学习框架的整体流程始于人类用户,具体如下:

  • **指令发送:**人类用户向 Controller(大模型)发送一个指令;
  • **规划:**大模型接收指令后进行一系列的规划,如复杂的任务需要的步骤以及每个步骤所需的工具集。
  • **反馈:**每个工具环境中去执行后,都会得到环境的反馈,例如给到搜索的信息或者给到该任务是否可以成功的判断。同时,人类也可在过程中给出反馈。
  • **反馈总结:**感受器 perceiver 接收来自环境和人类的反馈,并将两部分反馈总结为最终的 summary 给到大模型。
  • **更新:**大模型依据接收到的 summary 判断工具执行的成败,从而对规划进行更新,或者进行下一步的工具决策。
  • **迭代:**上述流程循环执行,直到大模型判定已完成人类给到的 instruction 指令后退出。

(1)意图理解 Intent Understanding

在 ChatGPT 之前更多是 NLP 场景下的任务,大家的共识是模型理解语言比较困难。ChatGPT 出现后,大模型基于 Instruction Tuning 技术,具备了非常强的理解人类指令潜在意图的能力,可依据人的指令去解决真实场景下用户的 Query 问题。

image-93c9b684c0ae4529bc94207a7786811e.png-imageStyle

大模型将 NLP 任务包装为多种 instruction 格式,进行大规模有监督的精调(Fine-Tuning),实现从指令空间到模型认知空间映射的学习。上述训练后的大模型具备了在未学习过的指令上的泛化能力,且随着模型的增大,训练数据量的增大及 diversity 的增强,其泛化能力会越来越强。

工具学习场景下意图理解面临两方面的挑战:

  • 用户的 Query 存在模棱两可、含糊不清的现象。通常人会表达一个目标,并未写明一个具体的指令,如利用什么工具,用工具做哪些任务。因此模型需要面对人类复杂和 high-level 的 query 进行规划决策、匹配适合的工具。
  • 理论上,整个指令空间无限。面对无限的表达和个性化的指令,如何使得大模型更好地泛化到未知的指令是另一个挑战。

(2)工具理解 Tool Understanding

在大模型中,除了需要模型对人类指令进行准确理解外,模型对工具的理解同样至关重要。首先,模型需要理解工具的功能;其次,模型需要知道如何在特定的任务中使用这些工具。在 ChatGPT 出现之前,主要的模式是通过记录人类使用工具的行为,并让模型模拟这些行为以实现工具使用的学习。而随着 ChatGPT 的出现,我们可以通过 Prompt Learning,即在 Prompt 中给出工具的描述,让大模型理解并应用工具。这种基于 Prompt 的方式目前已经成为大模型使用工具的主流方法。具体 Prompting 有如下两种:

  • Zero-shot Prompting

提供一个描述任务的提示(prompt)来引导模型生成正确的输出。在 Prompt 中描述 API 的功能、输入输出格式、传参方式等,使得模型理解 API 如何使用。如下图,Zero-shot Prompting 给出了 forecast weather API,描述其功能、返回信息等,然后去解决"下周北京的平均气温是多少"的问题。

**优点:**不需要为每个新任务重新训练模型,节省了大量的计算资源;并且可以快速适应新任务,只需为任务编写新的提示即可。

**缺点:**性能通常不如使用特定任务训练数据进行 Fine-tuning 的方法;且编写有效的提示需要一定的技巧和经验。

  • Few-shot Prompting

不仅给出任务描述性提示,还要直接展示少量(few-shot)的使用工具的示例,模型通过模拟人类的行为,理解如何使用工具。如下图,Few-shot Prompting 给出了调用 API 的示例(如何回答问题---明天上海的温度),然后再让大模型利用 API 去解决问题。

优点:利用少量示例帮助模型理解任务,提高了模型的性能。比 Zero-shot Prompting 更灵活,可以应对更多种类的任务。

缺点:需要选择有代表性的示例,这需要一定的专业知识和经验。对于一些复杂的任务,可能需要更多的示例才能达到满意的性能。

image-7e4c5999cf1d43b19f362ca1d2f8e91d.png-imageStyle

(3)规划与推理 Planning and Reasoning

大模型除了理解工具和人类的指令,还须具备规划和推理能力。

image-1e6c8a0f4b1240d5ae01c7db76d1bebb.png-imageStyle

依据规划与环境是否交互,模型的推理分成两种:

  • Introspective Reasoning

大模型首先生成多个候选答案,然后自评估答案的优劣,最后选择最优的答案。

模型生成一个静态规划(给出未来任务列表),不与环境交互,适用于简单的场景。

如果 Prompt 指令合理,早期的预训练语言模型(Pretrained Language Models)已经具备理解和使用上下文的 incontext 能力,可将 high-level 的任务有效地分解为 mid-level 的规划,而无需进一步的训练。

image-ae8f3bb57087404ba548cb031b7e7f65.png-imageStyle
  • Extrospective Reasoning

大模型默认解决方案,不断根据每一步的成败以及环境和人类的反馈,动态跟进该规划,直至整个流程完成。

挑战: 模型的自省式推理生成静态规划 Plan 存在一定问题,最优的方案是模型可以很好地在下游任务中落地。文章 Ahn, Michael, et al. "Do as i can, not as i say: Grounding language in robotic affordances." arXiv preprint arXiv:2204.01691 (2022) 提到:不是模型想做什么就做什么,而是让模型知道当前场景下能做什么才去做什么。

方案1:

image-0a7df9900ef54b778036063e925ee714.png-imageStyle

上篇论文通过设定 value function 限定了模型在每种场景下可做的任务,模型在某一场景下,只在上述的限制任务集合中进行选择,可以保证模型的可执行。

方案2:

Inner Monologue 这篇工作将不同来源的反馈信息注入到模型规划中,例如静态反馈------每次执行后环境的变化,动态反馈------人主动告知该任务是否成功等。基于环境反馈的模型能更好地进行推理和规划,达到更好的效果。

image-c4cf791fe4e94124a3b2aa0ff42c252e.png-imageStyle

可解决多步或多工具场景下的复杂问题的模型

  • **必要性:**人类并不只局限于某一个特殊场景,或只使用某一个特定的工具,通常会协调使用多个工具,解决复杂问题。
  • 研究探索:

不同工具之间的依赖关系

不同工具并行化执行(模型的生成是流式的)

单一Agent到多Agent协同执行任务(已发布AgentVerse 工具包
https://github.com/OpenBMB/AgentVerse

(4)训练策略 Training Strategies

大模型下,虽然直接 Prompting 就可以让模型学会使用工具,但在具备一定数据的特定场景下,进行微调通常都会有收益,除非数据的质量有问题。大模型学习使用工具的方式有两种:

  • **人类行为克隆,**人类向大模型展示如何使用工具,给到描述和注解。
  • **试错中探索,**通常基于强化学习,大模型从与环境和人类的交互反馈中不断学习。
image-0770105eaa07490193875ad1bfe8719f.png-imageStyle

2. WebCPM

(1)WebGPT 介绍

2021 年 12 月 WebGPT 的发布标志着基于网页搜索的问答新范式的诞生,该篇工作*(Nakano, Reiichiro, et al. "WebGPT: Browser-assisted question-answering with human feedback." arXiv preprint arXiv:2112.09332 (2021))* 可以算是工具学习领域最早期的工作,其做法为基于人类记录的大量搜索引擎使用的行为数据进行有监督 Fine-Tune 和强化学习,使得大模型学会使用搜索引擎。该文证明只需 6000 条数据就可让模型很好地学会如何使用搜索引擎,且能力会超越人类专家。

image-76795f305e994603b7ebdf56d8a8aa96.png-imageStyle

(2)WebCPM 介绍

鉴于 WebGPT 并未开源,相关工作不透明。因此,我们进行了 WebGPT 复现,完成了中文领域首个基于交互式网页搜索的问答开源模型框架 WebCPM,提供了第一个中文 LFQA 数据集,information retrieval 信息检索数据是基于网络搜索的交互信息拿到的,相关工作收录于自然语言处理顶级会议 ACL 2023。

论文地址:
https://arxiv.org/abs/2305.06849

项目地址:
https://github.com/thunlp/WebCPM

  • 本文地址:大模型工具学习探索
  • 本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
image-420685194d9d4f799dc4cb24b17e5366.png-imageStyle

(3)WebCPM 搜索交互界面

image-fb37da52419e46e096bfe94539bc9c1d.png-imageStyle

接口特点:可以搜索相关事实,记录相关事实,同时记录大约 10 个交互 action 行为信息。

(4)WebCPM 数据集

image-41600ffe07e342c88a7b5b79da33c994.png-imageStyle

WebCPM 的数据集包含 5500 对高质量的问题-答案对以及十万多条真实用户网页搜索行为。

LFQA 数据样例特点:

  • 记录搜索过程的 action
  • 记录抽取出来的多条事实依据,有标注的事实的 label
  • 基于事实依据生成最终答案

(5)LFQA pipeline 框架

WebCPM 建模包含两类模型:

  • Web Search 模型,(给定问题,得到相关摘要)执行一系列 action,收集相关的信息

Action 预测模块(预测在该平台的下一个 action,大约 10 个 action,建模为一个多分类任务)

Query 生成模块(生成搜索的 query,用文本生成来实现,P(Qt+1|St))

Fact 抽取模块(对当前页面抽取摘要)

  • Information Synthesis 信息合成模型(给定问题和摘要,生成最终答案)搜索出来的数据会存在噪音:训练数据中引入噪声,使其具备一定的去噪能力,从而忽略不相关的事实,只关注重要的事实以生成答案。
image-311e2b98e5f14fb0b59a171b56124f7e.png-imageStyle

(6)整体 pipeline 评测

  • pipeline-collected:指 WebCPM 的 pipeline 提取事实方法,模型生成的答案在 32.5%(19.0+13.5=32.5)的情况下与人写的答案相当或更优;
  • human-collected:将人工收集的事实应用于信息综合模型时,性能提升到了16.0+29.5=45.5,可归因于收集的事实质量的提高;
  • Non-interactive Search:指利用非交互式方法收集的 fact,效果较差,说明 pipeline 方法的优越性。
image-329daebea26443269df3eb1e798708ba.png-imageStyle

WebCPM 工作是在 ChatGPT3.5 发布之前,当时的基础模型与 ChatGPT 还是有一定的差距,随着 CPM 模型的改进,当前内部测试发现可以远超人类水平。

3. 其他工作

(1)WebShop

大模型如何学会使用亚马逊购物网站?可以类似搜索引擎,构建 WebShop:

  • 记录亚马逊中文网站上的主流操作,搭建平台接口
  • 人类使用上述平台接口
  • 记录人类行为信息
  • 大模型学习上述人类行为信息
image-886e95b703ef4e028b5d7adadcd14dc4.png-imageStyle

(2)Toolformer

WebCPM 和 WebShop 都需要让大模型学习大量人类标注数据,如何让大模型可以触类旁通学习,降低人类标注成本或降低人类的参与度?

动机:

  • 模型应该自行地去决定在何时间,用何方法来调用工具
  • 模型对工具的使用应该是自监督的,这样可以省去很大的标注开销

方法:

  • 受到 in-context learning 的启发,给定少量的人写的关于 API 的描述,让模型去自行生成潜在 API 调用的语言建模数据
  • 构建一个自监督的 Loss 函数,让模型来决定哪些 API 的调用有助于它的语言建模的预测

步骤:

给定一个纯文本数据集,构建出一个带有 API 调用的数据集,然后在此数据集上做微调

  • 在大规模无标注语料上,使用 in-context learning 来生成大量的潜在可用的 API(每个 API 为一个具体的工具)
  • 执行这些 API,返回得到结果
  • 检查返回的结果是否有助于语言模型的预测,过滤掉其他的 API
  • 构建一个高质量的工具调用数据集,进行模型微调
image-679c4e0e4a4e4d299442bde4b4eb3b66.png-imageStyle

Toolformer 这项工作展示了大模型具备很强的自学的能力, 大模型可自主学习工具,并可不断提升工具使用的能力**。**

(3)Tool Creation

在证实大模型可以使用工具后,我们的 Tool Creation 工作在整个领域首先提出了模型作为工具创造者的想法。在 21 世纪之前,通常认为人类是工具创造和使用的主要主体,而基础模型的出现可能颠覆这一观念,创造工具不再是人类专有的能力。

每个任务其实最好都是能用工具解决,现实场景下不一定存在最适合解决该任务的工具,可以通过大模型生成解决该任务的工具。人类创造的工具都是为人类设计,为人类设计的工具不一定是最好的,大模型可以定义更加适合自己的工具接口,该接口不一定适合人类使用。通过初步验证,大模型可以将一个简单工具 API 升级为具有更好功能的工具,基础模型可能具有自发创造工具的潜力。

image-60b1faea68f649ebb6c106c33e2b4d56.png-imageStyle

所以我们提了这样一个框架,给定任何一个 query,我们会让模型先去做一遍工具的生成。具体包含四个步骤:creation、Decision、Execution、Rectification。

从现有的工具库中选择相关的工具,然后对这些工具进行升级。完成工具升级后,模型可以具体调用这些工具来解决任务。假设模型发现当前的工具并不适合解决当前的任务,那么它可以回到升级或创造工具的阶段,继续优化工具或创建新的工具。

这个过程会持续进行,直到模型创造出一个能够有效解决当前任务的工具,就可以跳出这个循环。这种设计使模型具有了持续学习和自我优化的能力,从而提升了其解决问题的效率和效果。

image-c4fc9c1b03114266953557d930ba81fe.png-imageStyle

通过实验发现增加工具生成,使得解决实际任务的能力增强,相较 PoT 和 CoT 都有显著的提升。

image-85dbf4a399a44c55912df8c4adb5e90a.png-imageStyle

工具的创造过程从本质上说是降低了后续任务的难度。如果只有一个质量很差的工具,那么可能需要付出巨大的精力才能使用这个工具来解决一个复杂的任务。所以,从这个角度出发,引出我们工作的核心理念:先创造工具,再用这个工具去解决任务。

03应用 Application

1. 开源平台 BMTools

(1)ChatGPT 插件

OpenAI 发布了支持联网、解决数学计算的插件 ChatGPT Plugins, 被称为 OpenAI 的"App Store"。然而,由于目前其仅支持部分 OpenAI Plus 用户,大多数开发者仍然无法使用。

image-7fe49dcaa16f4139ba5d613d7295b26e.png-imageStyle

(2)BMTools 介绍

为解决这个痛点,我们推出了 BMTools 工具学习包,一个基于语言模型的开源可扩展工具学习平台。

BMTools 工具包:
https://github.com/OpenBMB/BMTools

image-a540c34a22f24562a98191becaaabbaa.png-imageStyle

我们将各种调用流程统一到一个框架上,使整个工具调用流程标准化、自动化。开发者可通过 BMTools,使用给定的模型(ChatGPT、GPT4)调用多种工具接口,实现特定任务或功能。

BMTools 具有如下一些特性:

  • 在 Huggingface Spaces 上可直接试用;
  • 支持自定义新工具,开发者只用编写简单的 python 程序就能轻松构建新的插件功能,允许开发者扩充工具库;
  • 支持使用已有的工具如 ChatGPT plugins;
  • 支持使用本地模型,可接入 Stanford Alphaka、CPM Bee 等;
  • 在 planning 层面,支持 Lang chain 框架,支持 baby AGI 和 auto GPT;
  • 100K+ 工具使用的SFT数据即将发布;
  • 支持 30+ 工具,包括数据库,天气 API,PPT、谷歌搜索引擎、图像生成、Huggingface 模型等。
image-0cac3735214c4dee8ae85598af91ea49.png-imageStyle

2.ToolBench

ToolBench 项目,可以帮助开发者构建开源、大规模、高质量的指令调优数据,促进构建具有通用工具使用能力的大语言模型。

image-ea08370845724e1f9fac88ac7e33ee31.png-imageStyle

链接:
https://github.com/OpenBMB/ToolBench

ToolBench 工具包特性如下:

  • 支持单一工具和多工具配置。对于单一工具的配置,采用了 LangChain 的提示风格;而对于多工具配置,则参照了 AutoGPT 的提示风格。
  • 模型的回复不仅仅包含最终的答案,还涵盖了模型的思维链条过程、工具的执行以及工具执行的结果,以实现对模型的深度理解。
  • 具备处理真实世界层面复杂性的能力,支持多步骤的工具调用,从而能够应对各种复杂的任务需求。
  • 提供丰富的 API 接口,可用于现实世界中的各种场景,包括但不限于获取天气信息、进行网络搜索、更新股票信息以及实现 PPT 自动化。

构建过程:

ToolBench 基于 BMTools,在有监督数据中训练大语言模型。所有的数据都是由 OpenAI API 自动生成并由开发团队进行过滤,数据的创建过程很容易扩展。

image-7f5c06d5d73b424c9e5d78ce0d52ca51.png-imageStyle

ToolBench 仓库中提供了相关数据集、训练和评估脚本,以及在 ToolBench 上微调的功能模型 ToolLLaMA。仓库中包含 31.2 万次真实 API 调用得到的 9800 条数据。

image-f8bd380aee874099be0313fe41d275ee.png-imageStyle

ToolLLaMA

通过 ChatGPT 对 LLaMA 和 ChatGPT 的答案和工具使用链进行自动评估。

评估结果如下(分数越高越好),ToolLLaMA 在不同场景下与 ChatGPT 的性能相同或更好。

image-7fae7978eda3495dad8d2bdedcc185a5.png-imageStyle

3. 工具学习必读 Paper List

工具学习论文列表:
https://github.com/thunlp/ToolLearningPapers

image-f251e403273644e8a24e20abaf9e5e18.png-imageStyle

04问答环节

Q1:Web CPM 是否针对网络中网页搜索质量低,进行搜索结果过滤等设计?

A1:WebCPM 针对页面低质量搜索内容进行了过滤。

  • 必应搜索引擎返回的内容与 Query 的相关性较高,底层网页层面未进行过滤;
  • 针对具体的某个页面内容,调用现有的一些筛选器,如中文有简阅的插件,可过滤掉广告、保留页面中重要文本内容。

Q2:在不同语言上的效果如何,例如在中文任务上的效果怎么样?

A2:WebCPM 背后的基础模型 CPM 是由面壁智能与 OpenBMB 开源社区开发的百亿参数中文语言模型,占据多个中文领域语言模型排行榜前列。

Q3:Web CPM 和 Web GLM 的区别?

A3:WebCPM 的主要特点在于其信息检索能力基于交互式网页搜索,能够模拟人类与搜索引擎的交互过程,以收集回答问题所需的事实性知识,并据此生成答案。其核心关注点在于评估模型能否像人类一样智能地使用一个框架,目标在于模拟人类的行为和思考过程,而非超越人类。此外,我们也关注在使用最少量的数据的情况下,能够让模型达到尽可能接近人类的表现水平。类似 WebGLM,我们在开源仓库中提供了一套包含数据集的固定流程方案。

WebGLM 则是一个基于大语言模型(LLM)的联网问答聊天机器人,其工作流程是固定且流程化的,包括搜索、页面检索、页面信息摘取和总结等步骤。这一框架为进一步提升每一步骤的能力提供了极好的基础,随着每一步骤能力的增强,最终的模型效果有可能超越现有的大模型。

以上就是本次分享的内容,谢谢大家。

image-ab7487ed07404624ba635ca8c791b7f9.jpeg-imageStyle

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK