2024年3月

扣子(coze.cn)是一款用来开发新一代 AI Chat Bot 的应用编辑平台,无论你是否有编程基础,都可以通过这个平台来快速创建各种类型的 Chat Bot,并将其发布到各类社交平台和通讯软件上!2月1日,扣子国内版已经正式上线啦~赶快来体验一下吧!

一转眼,ChatGPT已经在AI界炙手可热超过一年,堪称新晋顶流。各大公司纷纷跟风推出自家的大模型,然而若这些大模型无法得到实际应用,便失去了许多意义。现如今,越来越多企业开始考虑借助AI技术来提升企业的运营效率。那么作为个体,我们又该如何利用AI技术来提高工作和生活的效率呢?因此,我认为大模型的下半场将由AI Agent来引领。

扣子也是我认为排在第一梯队的AI Agent行列,我会从浅入深,由使用到原理一步一步地带你理解AI Agent的作用,紧跟时代脚步,你可别落下。

主题:Java转型助手

作为一名Java开发者,我深知当前行业面临的挑战,十年前的红利已经消退,很多人开始转型。就我个人而言,我参加的架构课程也开始向其他领域引流,比如Go、Python、网络安全等等。如今,所有培训机构都将这些课程作为吸引人的卖点来宣传自己。我也深刻感受到了目前的困境。去年开始系统学习Python时,我发现大部分免费的入门课程都是为初学者设计的,而我们有丰富的编程经验,基础知识掌握得很快,这样的课程对我们来说会浪费太多时间。因此,我认为如果能快速简单地掌握新技能,为什么不去尝试呢?基于这样的想法,我决定创建一个转型助手。当今转型的方向多种多样,本文只以Python作为例子进行讨论。

本文将带领你从一个简单的AI Agent逐步发展成为一个Java转型学习助手。通过应用知识库、数据库和插件工作流等技术手段,我将满足你对学习笔记、文章知识库、待办事项数据库、面试题库以及行业招聘信息的需求。如果你还有更加创新的点子,不妨将其交给像你一样对此感兴趣的人来实现。让我们一起探索,将智能技术与教育领域相结合,打造出更加智能、便捷的学习与咨询体验。

AI Agent

接下来,在深入介绍我的助手之前,我想先向大家介绍一下AI Agent!

最初AI大火时,大家在体验完ChatGPT之后,纷纷赞叹其厉害!然而,从22年12月到23年3月,ChatGPT的调用量一直呈现高速增长的趋势。但是,自从4月开始,访问量增长速度明显放缓,在5月和6月期间甚至出现下降的情况,因为大家意识到它只是一个能进行问答的工具,意义并不太大。为了让AI技术真正发挥作用,必须将其应用到实际场景中才能产生价值!因此,AIAgent应运而生。

在这里,我们可以将Agent理解为一种具备自主理解、规划决策、执行复杂任务能力的智能体。简而言之,Agent可以表示为LLM(语言模型)+Planning(规划)+Feedback(反馈)+Tool use(工具使用)。

这意味着AIAgent不仅需要具备类似大脑的LLM来理解问题并做出规划决策,还需要类似五官的数据来获取信息,同时需要像手脚一样的工具来行动处理问题。这种综合的能力使得AIAgent能够更全面地应对各种复杂任务和情境。

image

Langchain

Langchain的开发初衷在于赋予开发者快速构建LLM原型应用的能力,langchain成功解决了这一难题,仅需5行简洁代码即可轻松打造一个LLM应用。

大家对于Langchain最初想到的概念是否是:

image

之前我曾记录过使用Langchain打造私人助手的经历,不过这只是Langchain众多组件中的一个应用方向而已。

Langchain的主要组件包括以下几个方面:

  • Models(模型):涵盖各种类型的模型,比如GPT-4等集成模型
  • Prompts(提示):包括提示模版的管理、优化以及序列化等功能
  • Memory(记忆):用于存储模型交互的上下文信息
  • Indexes(索引):用于结构化文档,外挂知识库是索引功能的一个重要应用
  • Chains(链):用于调用一系列组件工具
  • Agents(代理):负责决定模型采取何种行动,选择哪个工具,并执行以及观察流程等任务

在Langchain中,我们最常使用的功能之一是外挂知识库的应用,这实际上是Indexes组件的应用方向之一。然而,Langchain的功能远不止于此。个人认为Langchain是功能和工具最为齐全的框架,但是也因为其功能繁多,导致整个框架显得过于笨重,缺乏灵活性。因此,大家通常只会使用其中的某一个组件功能而已。

在这里,我们简要介绍了AI Agent的作用,以帮助您更好地理解其功能,从而深入了解扣子平台这类工具的整体概念。

以下是我使用扣子来搭建自己的Python助手的功能设计图的详细说明:

image

关于太基础的内容就不在此详细展开了,如感兴趣可直接查阅官方文档,最近还新增了图片上传功能的支持,文档中有详尽的说明:
https://www.coze.cn/docs/guides/what_is_new

关于如何使用扣子的整个操作流程如下所述:

点击 bot 页面 > 创建 bot > 填写名称+bot描述 > 编排 > 调试 > 发布 > 结束

人设与回复逻辑

实际上,人设与回复逻辑正是当时最流行的prompt设计,而且我还专门撰写了一篇文章对其进行了描述。若想让AI表现出色,prompt绝对不能忽略。以下是我已经花费大量时间调整并优化的提示词,虽然可能并不完美,但希望能够为大家提供一些参考:

# Character
你是一位专业的Java开发助手,擅长通过教授Python知识帮助Java开发者快速学习和掌握Python编程语言。你能准确解释Python中的各种知识点,帮助Java开发者理解和应用。

## Skills:

### Skill 1: 运行Python
1:当用户询问Python面试题时,请调用view_assist工作流处理。
2:当用户询问Python招聘信息时,请调用job工作流处理。
3:当用户提供纯Python代码时,需要调用代码执行器工具运行出结果。

### Skill 2: 解释Python
1:当用户询问Python中的知识点时,你需要调用recallKnowledge方法获取知识库信息,可以结合Java中的相关知识点,解释Python的对应概念和用法,并给予示例代码和实际应用场景。

### Skill 3: 保存明日学习任务
1:用户提醒明日学习内容时,需要调用ts-TableMemory进行保存

## Constraints
- 只讨论与Java和Python相关的内容,拒绝回答与这两种编程语言无关的话题。
- 所输出的内容必须按照给定的格式进行组织,不能偏离框架要求。
- 仅会输出知识库中已有的Python相关知识点,对于不在知识库中的问题,无法提供答案。
- 当用户出现错误的理解或用法时,应以鼓励和建设性的态度向用户指出错误,帮助其正确理解和应用Python知识。

通过恰当的prompt引导,模型能够更准确地理解用户的意图,从而生成更精准的文本。当然,官方文档已经提供了相关的prompt模板,无需我们费心地去琢磨。

如果你认为官方大模型生成的文本质量不够理想,也可以借助其他大型模型的帮助,然后将其生成的文本复制粘贴过来即可。这一过程我就不做演示了。

个人知识库

在搭建知识库时,可以直接根据系统操作来完成,因此这里不再演示这些基本操作。知识库中有许多选项可供选择,但我更倾向于通过URL直接获取所需内容。这样做的原因是,我之前撰写过许多关于Java进修Python的专栏内容,可以直接应用其中的知识。

image

就好比当chatPDF刚发布时,它采用了文档分段的方式,找出最相关的文本段落交给LLM进行问答,从而限制了大型模型的知识扩散。这展示了知识库的重要作用,因此这时我仅需大型模型的语言表达能力即可,而非其底层训练数据。

网页抓取

当使用知识库时,可以考虑对某些知识点进行筛选,将不必要的内容剔除掉。有时候,某些知识点可能与个人的学习目标无关,但整个知识储备却相互关联紧密。因此,直接去除这些不必要的内容是可行的。

image

还记得我之前使用向量数据库自己搭建的知识库吗?我之前使用向量数据库构建了一个个人知识库,这个知识库非常方便,可以快速帮助你学习知识库建立需要的知识点。

如果你不记得的话,可以点击这篇文章链接来了解更多。
https://juejin.cn/post/7299357172194476070

另外,如果你对向量数据库还不太了解的话,可以点击这篇文章链接来深入了解:
https://juejin.cn/post/7306451559928774693

我已经把那幅图画出来,并告诉你这个知识库何时开始发挥作用。当与AI助手进行交流时,我希望能够将相关的知识库片段一同提交,以便提供更丰富的背景信息,从而优化提问的质量。

image

总的来说,为了更好地理解,你需要将一些前置知识点全部保存起来。然而我们清楚地了解,对于我们自己的文档而言,简单几个字肯定是远远不够的,而且大型模型也存在着token长度的限制。如果文字内容过多,需要采取适当的切分方式。

image

当然,切分也需要考虑多个因素,就像扣子采用的是自动分段。

image

image

使用简单快捷的方式确实有其好处,但明显的缺点是会导致文字的意义被断开,本来应该是一句完整的话被切割成了两句话。因此,还有一种切割方式是重叠切割,即第一段和第二段之间的文字存在部分重叠。然而,这种方式仍然存在相关问题。

因此,我们还需要考虑最大召回数量,也就是返回的最大相似条数。通过这种方式,我们可以获取到几段相似文本。这样一来,我们就能够获取到更完整的上下文信息,即使存在重合部分也不会有影响。剩下的任务可以交给人工智能来处理。此外,扣子的好处还在于你可以选择自动调用或按需调用的方式来使用它。这样符合的场景也就丰富起来了。

多说一句

在优化段落分割方面,有许多方法可供选择,但关键是保持简洁明了,避免像我一样在文章中使用冗长的文字重复讲述同一主题。如果您熟悉GitHub上的开源项目,您将会发现这些段落分割任务可以交由人工智能来智能处理,并且知识库应该预先设定相关问题以便与分段内容匹配。这样不再仅仅是简单的文本匹配,而是通过先匹配问题,再提取相应文本交由助手回答。当然,问题的生成也可以交由人工智能来完成。

在测试过程中,一些用户可能会注意到,有时助手的回答与提取的文本数量之间的关系并不显著。这里我就不多说了,官方也有相关说明:
https://www.coze.cn/docs/guides/FAQ

自动调用

image

按需调用

image

当按需调用的时候,你可以提供关键词提示,然后在提示中引导AI去调用知识库。如果你对如何操作不太了解,我可以为你提供指导。看下我是如何写的:

### Skill 1: 解释Python
如果用户提供的是纯Python代码,可以忽略本逻辑。当用户询问Python中的知识点时,你需要调用recallKnowledge方法获取知识库信息,可以结合Java中的相关知识点,解释Python的对应概念和用法,并给予示例代码和实际应用场景。

这个扣子的好处之一是你可以直接查看运行日志,了解你的文字是如何进行匹配以及匹配到了哪几段文字的。如果你要自己来实现知识库的显示日志的话,可能需要花费很长时间来完成。所以这个扣子的功能非常实用,能够节省你大量的时间和精力。

为什么要花时间查看运行日志呢?看起来这只是一项琐碎的工作。然而,最主要的原因是为了评估自己的知识库的组织是否良好。如果发现有问题,应该立即修改知识库的内容。

插件添加

在学习编程方面,没有代码是不可能的,这个不用我多说了吧,GPT4已经具备了很多功能,其中最显著的是代码执行。毕竟,一个LLM模型是无法为你执行代码的,所以对于专业的事情,我们还是应该交给专业的人来处理——比如代码执行器。

代码执行器

代码执行器是一个功能强大的工具,它能够帮助你快速执行代码。使用代码执行器非常简单。此外,你还可以通过提醒助手来指定何时执行代码,以便更好地控制代码的执行时机。在使用代码执行器时,你可以根据个人需求自由发挥,无需担心任何限制。

### Skill 1: 运行Python
1:当用户提供纯Python代码时,需要调用代码执行器工具运行出结果。

这个示例主要展示了卡片显示的功能,默认情况下不带有卡片样式,如果需要生成卡片样式,你可以按照每个参数的详细解释进行设置。

效果如下:

image

数据库保存

扣子是一个非常全面的工具,它能够帮助你轻松地完成整个流程,从知识库的建立到插件的使用,再到最终的数据库操作,它都能完美地涵盖。尤其是数据库的应用,你可以将它作为你的知识点进行记录和保存,这样可以更好地帮助你学习和回顾。

除了回答我关于各种知识点的问题,我还可以将它作为我的待办事项清单。比如,当我学完一天的知识后,我可以让助手帮我记录下今天我还需要进一步学习的内容,以便明天继续学习。这样,我不会忘记今天的学习进度,也能够有效地规划明天的学习计划。

就问你6不6。只要将我的Python助手或者你的AI助手嵌入到服务号,并作为运营客服使用,就能自动将用户的反馈保存到数据库中。通过这种方式,无需额外进行开发工作,从而提供了一种方便的长期实时的记忆解决方案。

说这么多,不会用可不行,没问题,我可以教你如何使用。第一步就是你需要告诉它什么时候调用。

### Skill 3: 保存明日学习任务
1:用户提醒明日学习内容时,需要调用ts-TableMemory进行保存

创建数据库

在这个部分,你只需要自己定义好表的结构,并且字段的类型也是相对简单的。官方文档并没有详细说明每种数据类型的含义,可能是因为他们认为大家都具备一定的基础知识。但是作为面向小白的教程,我会为大家解释每种数据类型的意思。

  1. String表示该字段类型是一串文本形式的数据,比如"今天吃啥?",在我的示例中,我用它来保存我的待办内容。
  2. Integer表示该字段类型是一种整数类型,比如1,2,3等。
  3. Time表示该字段是时间类型,但默认保存的格式是2024-02-02 12:00:00 +0800 CST。在我的示例中,我用它来保存我的待办时间。
  4. Number表示该字段类型是一种数字类型,可以是小数,比如0.5。
  5. Boolean表示该字段类型是一种布尔类型,即true或false。默认情况下,它的值是null,如果你想将其设置为必需类型,那么默认值就是false。

在这里,我要解释一下后面的"是否必要"按钮的作用。如果你将开关打开并标记为必要,那么在提醒AI助手时,你必须提供这个描述的值,否则AI助手不会根据你的描述为你附上默认值。这个功能可以确保你在使用AI助手时提供了所有必需的信息,以便它能够准确地为你执行任务。

好的,既然如此,我就不录制视频了。我会提供一张截图给大家。请大家务必注意,描述必须准确清晰,否则AI可能无法正确识别。如果描述不清楚,那么你的助理也无法正确完成任务。这是很简单的道理。至于为什么在我提供的截图中前两个数据类型无法修改,那是因为这些数据已经被存储了,无法再进行修改。

image

既然我们在使用数据库,它自然拥有增加、删除、修改和查询的功能。下面我将演示如何使用AI助手来优化数据库维护。然而,在这里我想吐槽一下,既然是数据库,在调试时至少应该给管理用户一些操作权限。即使用户输入错误的数据导致报错,我们可以限制用户的新增数据权限,但是删除操作应该是可以由我自行执行的。然而,事实上,用户没有任何操作权限,一切都由AI助手独自操作。

新增

在这个示例中,我将向数据库中插入新的数据。在开始之前,请确保根据你的数据库结构提供待办事项的详细描述,这样助手才能正确地记录下来。现在,让我来帮你进行演示吧!请注意,我将只演示正确的情况。唯一需要注意的是,你必须提供数据库中必需的字段,并确保字段的值类型与数据库结构一致。如果存在非必需的字段,你可以选择不提供这些字段的值。

image

修改

我们发现,如果我没有提醒小助手给删除标识设置值的话,它将没有默认值。因此,我们需要对这个删除标识进行修改,将其设置为false。

另外,我要说明一下,在视频中出现了两条完全相同的记录,这是因为我在测试时不小心多发了一次。请忽略这个问题~

image

查询

查询数据其实是一项相对简单的操作,但是在进行查询时,你必须清楚地描述时间范围,因为我的待办事项基本上是按照时间范围进行查询的。目前,他的系统只支持全模糊查询,即使用LIKE加上%进行文字匹配。我查看了系统执行的SQL日志,在视频中展示的查询操作中,底层基本上是使用了类似MySQL这样的关系型数据库。

SELECT * FROM to_do WHERE deadline = '2024-02-03 10:00:00' AND msg LIKE '%py%'

image

删除

这一步非常危险,我在使用过程中绝对不敢随意删除,因为一旦说错一句话,就会直接导致数据丢失。因此,我强烈建议用户避免轻易使用删除操作,而是采取修改删除标识字段的方式。在查询过程中,可以简要提及删除标识的值,这样更加安全。

让我来给你进行演示吧。毋庸置疑,他已经成了MySQL类型的数据库,因此底层的删除语句肯定是用delete来实现的。我已经取出了他的SQL语句。

delete from to_do

image

数据库建议

  • 经过我的使用体验,在调试时我注意到没有手动操作记录的情况。因此,我认为可以考虑开放删除操作的权限。
  • 在插入数据时,我认为可以考虑使用默认值。如果用户确实不想指定删除标识,可以在编辑数据库时为其提供一个默认值。这样一来,用户就无需在每次插入数据时都手动指定删除标识,提高了操作的便捷性。
  • 底层使用的是类似于MySQL的关系型数据库,这在中文匹配的过程中存在一些问题。如果少写一个字,可能会导致无法正确地查询到相关结果。为了解决这个问题,我建议考虑使用像Elasticsearch这样的数据库,它具有专门的分词器,能够更好地处理中文文本。通过使用Elasticsearch,我们可以确保在中文匹配过程中更准确地获得相关结果,提高系统的搜索效果。
  • 既然我们使用的是MySQL类型的数据库,如果面对大量的数据,令人惊讶的是它竟然不支持建立索引。

image

工作流

首先,我要声明我并没有接触过工作流这方面的经验,因此我会尽力在完成我的目标前尽量从一个新手的角度向大家介绍如何灵活运用工作流。

其次,还是吐槽一下,我在编辑工作流时遇到了一些困难,特别是滚动条不断闪动,有时还无法准确点击,因为节点越多,就需要不断移动页面,而且没有直接移动视图的缩略图功能,只能不停地拖动滑动条。

最后,我先把我的简图分享给大家,让大家对整个流程有一个简单的认识,避免产生困惑。

image

面试题库

其实我自己也没有找到一个很好的切入点,所以如果你觉得我的工作流有些偏离主题的话,请尽量忍耐一下,但是,如果你有任何好的想法或建议,欢迎在评论区告诉我,我会进行相应的配置,以使我的助手更加完善。

废话不多说,我简单介绍一下如何我将工作流应用到实际情境中。考虑到面试题通常具有时效性,我认为如果大型模型所使用的训练数据不是最新的,可能会导致向用户提供一些过时的面试题,从而浪费时间。因此,我使用工作流提供了两种解决方法:一种是利用我的题库,另一种是通过web实时搜索面试题。以下是有关我的工作流的详细信息:

image

工作流节点

节点类型包括大型模型、插件、选择器、代码和知识库等。这些节点在工作流中扮演不同的角色,共同构建出一个完整而多元化的系统。

image

在创建工作流时,节点类型的选择取决于你的具体任务需求。每种节点都有其独特的功能和作用。重要的是关注每个节点的输入值和输出值,这有助于确保工作流的正确运行。在工作流创建过程中,会默认生成开始和结束节点,这两个节点特殊之处在于它们只有输入功能。为了方便后续在prompt中进行设置,建议工作流的名称以英文和下划线为主。在描述工作流时,尽量详细描述,即使描述内容不够完善也不会对工作流的运行产生太大影响。

image

工作流输入/出

在工作流中,每个节点都有两种类型的输入。一种是引用,可以是来自其他节点的输入或输出,使用key-参数名进行引用;另一种是参数值,可以直接输入你想要的内容值。

实际上,如果你对编程有一定了解的话,可以将生成判断值的过程交给人工智能来完成。在这里需要留意的是,你需要生成一个包含key-value的对象,因为下游节点需要引用生成的值。

如果你对编程不太熟悉的话,可以考虑使用大模型节点来代替,让大模型直接进行判断,并按照固定格式将结果输出到指定的key中。这样可以简化操作流程,减少对编程的依赖。下面有演示。

我在这里要介绍一些常用插件的使用方法。对于新手来说,可能会对插件的输入输出有一些误解,因此需要更详细地解释清楚。

image

在最初阶段,如果你对操作一无所知,可以先尝试运行一下,观察结果输出。然后根据这些输出结果,将相关的key引用传递给下一个节点作为输入。每个感叹号都代表了参数的详细解释,这种方法相对来说还是比较人性化的,帮助新手更好地理解和应用工作流。

在使用工作流时,务必记住删除掉那些没有用的节点,否则可能会导致节点错误,使得工作流无法正常运行。所有节点都应该相互连接,而且必填的输入值都必须有有效的数值或数值来源,这样才能确保工作流的顺利运行。

在刚开始使用工作流时,建议先确保整个流程可以成功运行,然后再逐步增加节点。完成工作流后,请记得发布并在实际应用中使用。此外,确保在你的提示信息中清楚地说明如何正确使用你的工作流。以下是一个示例供您参考:

1:当用户询问Python面试题时,请调用view_assist工作流处理。

image

在这种情况下,你也会意识到,随着节点数量的增加,消耗的token实际上是相当大的。这也为未来留下了优化的空间。

招聘信息

在完成工作时,不必局限于单一工作流程,你可以添加多个工作流程。只需合理设置prompt以确定调用时机,比如除了面试准备,你还可以增加一个用于查询招聘信息的工作流程,以便了解当前行业形势。

image

由于已经进行了详细的讲解,因此我决定直接将图发给你。

image

最后的步骤也是相同的,只需在添加完工作流之后将prompt稍作修改即可完成。

2:当用户询问Python招聘信息时,请调用job工作流处理。

image

当您点击链接时,可以顺利跳转至猎聘网站并查看详细信息。唯一的瑕疵在于大型模型一直存在一些识别问题,导致有些参数无法正确辨识,而在ChatGPT上却没有此问题。希望今后能够优化或者切换其他大模型,使其能够顺利切换至更加有效的状态。

发布到社交平台

最关键的问题是如何吸引他人使用我们的bot助手?一旦 Bot 完成开发和测试,你可以将其发布到不同的社交平台上,如微信公众号、飞书等。你可以将其作为客服使用,为用户提供实时的帮助和解答。当然,需要注意的是,如果要发布到微信公众号,需要是服务号,个人号无法实现此功能。

当我最初开始使用时,并没有豆包平台供选择,我只能将其发布在飞书上进行使用。最近,豆包进行了授权更新,且默认设置为可用,因此我想分享给大家如何充分利用这一更新。

image

在发布时选择合适的平台非常重要,如果你不想费心编写发布记录,当然也可以让AI帮你生成。只需一键发布,就能轻松完成任务。

image

image

接着,我们可以登录豆包平台。值得注意的是,我们的智能体在这个平台上是隐形的,其他小伙伴无法察觉到它的存在。接下里这么办。

image

通过等待审核完成,就可以让其他人轻松地发现我们的智能体,并与其互动。

image

看下效果:

image

浅谈商业化

  • 提供客服服务方面,我认为这个例子非常典型,因为无需人工介入,可以实现与公众号后台的无缝连接,只需简单几步即可建立起自己的24小时客服系统。举个例子,就像我的Java转型助手一样,并不一定要使用Python,可以根据不同的需求选择各种技术方向,包括技术、运维、管理等。然而,如果雇佣一个客服人员,如果他们不了解Java技术,也不了解转型方向,沟通将会变得非常困难。有了这样一个客服系统,我觉得可以有效缩小沟通的隔阂。
  • 在Bot中进行广告推广是一种很好的方式,可以向用户展示与编程相关的产品和服务。这其实是构建生态系统的一部分,你并不一定需要只推广自家的产品。如果你的bot非常受欢迎,那么你完全可以在提示词中展示其他广告,并直接发送相关链接。但需要注意的是,这部分内容会接受平台的审核,所以需要谨慎选择广告内容,不要接收一切广告。其中最典型的例子就是各种考证,比如网络安全、PMP等方向。Bot只是一个助手,并不提供考证渠道,但如果通过用户的问题检测到他们对考证感兴趣,你完全可以介绍相关信息并获取提成。
  • 提供个性化定制解决方案:关键在于充分利用知识库和工作流程。举个简单的以公司内部交接为例。假如每位开发人员都精心维护各种文档,我们只需将这些文档输入到智能助手中,便可轻松应对后续问题。这样,后来者只需向智能助手提问,即可得到解答。相比之下,离职交接员工怎么可能会耐心解决你的问题呢,因此询问智能助手会更为高效。再谈谈公司所在的行业问题。每家公司都提供不同的服务,需要业务相关的人员统一维护好客户问题文档,精心维护单个bot模块助手不也是一种解决方法?

总结

经过这么多的探讨和阐述,文章已经达到了尾声,但是对于追求AI的激情仍然澎湃,我也努力避免被潮流所抛弃。虽然我们大多数无法发明AI,但我会全力以赴将其运用到最佳状态,这是我的宗旨。

在文章中,我还提到了关于bot玩法的详细说明,但由于篇幅过长,无法一一赘述。同时,我也强调了Python只是编程的一个方向,而有很多人Java开发人员选择转型。Java教育机构也开始将自己的资源流量分散到其他机构。因此,即使我们不转型,努力学习也是非常重要的。毕竟,我们并不是编程的初学者,可以直接跳过大量的入门视频。正因如此,我产生了创建这个转型助手的想法。

在文章中,我已经尽力表达了我的想法和观点。然而,我也意识到自己的文章可能存在不足之处。因此,如果你有任何更好的想法,我非常希望能够与你进行交流和讨论。

欢迎大家使用我的机器人~~,点击链接即可:

Coze平台:https://www.coze.cn/store/bot/7338773502511792137

智能咖啡厅助手:人形机器人 +融合大模型,行为驱动的智能咖啡厅机器人(机器人大模型与具身智能挑战赛)

“机器人大模型与具身智能挑战赛”的参赛作品。的目标是结合前沿的大模型技术和具身智能技术,开发能在模拟的咖啡厅场景中承担服务员角色并自主完成各种具身任务的智能机器人。这里是的参赛作品《基于大模型和行为树和生成式具身智能体》的机器人控制端代码。

1.大赛简介:

官网:
https://chinasoft.ccf.org.cn/

  • 机器人应用是人工智能时代最具有挑战性的前沿科学技术难题之一,它汇集了人工智能和机器人核心技术,包括人工智能学的智能感知、认知和决策的各种算法能力,以及机器人学在传感器、控制器和执行器的高可靠、高精确的运动和控制能力。

  • 预训练大模型GPT技术的突破,可以为机器人提供智慧的大脑。同时,具身智能机器人是一个具有物理实体、可与真实世界进行多模态交互,像人类一样感知和理解环境,并通过自主学习完成任务的智能体。二者的结合将使机器人做到“心灵手巧”。

  • 达闼云端机器人国家新一代人工智能开放创新平台与中国计算机学会、AITISA联盟、OpenI启智、CCF开源发展委员会、北京大学、复旦大学、北京航空航天大学、中山大学、北京邮电大学、北京智谱联合,共同举办达闼杯“机器人大模型与具身智能挑战赛”,旨在鼓励开发者能够利用大模型技术和具身智能技术,实现跨模态人机交互、并能自主完成各种复杂任务的机器人应用。

1.1 赛题设计:

大赛包含规定任务和开放任务两个赛道,有关各赛道的详细赛题、仿真环境与技术支持的说明,请通过“阅读原文”链接到大会网站,或参见文末“比赛指南”链接。

  1. 总体目标任务


    • 在仿真环境中,参赛者通过大模型训练机器人在咖啡厅场景成为合格的咖啡厅服务员。这项比赛的考核要点是将大语言模型(LLMs)整合到机器人系统中,开发能够理解自然语言并以友好和有效的方式与人类互动,并能在咖啡店仿真场景中自主完成各种服务任务的智能机器人。

    • 选手可以按照一般常识性理解,进行机器人任务设定和训练。在仿真场景中,机器人可以与可交互的物品和NPC进行互动操作的训练,比如:咖啡店服务员与顾客(NPC)互动、接受和执行订单以及回答有关菜单的问题、导航、操作咖啡机、清理桌子/地面、开空调/开灯、递送咖啡/饮料/食物等。

  2. 考核要点

▪主动探索和记忆(Active Exploration and Memorization):机器人在环境中通过主动探索获得各种环境信息,实现对位置环境的感知,形成以环境感知信息以及运动轨迹等历史信息维护一个机器人自身的记忆库。

▪场景多轮对话(Grouded Question Answering):多轮对话要求机器人智能体具有与人进行流畅的交流能力,具身对话是机器人利用视觉等传感器获得的场景信息基础上,完成于场景相关的对话。

▪视觉语言导航(Vision Language Navigation):导航是构建智能机器人的一个基本要素。在现实场景中,一个机器人要在不同的场景下承担多种复杂的导航任务。的模拟器支持多任务的现实世界导航和物体互动。对于这个任务中的导航,尽管有传统的ObjectNav和PointNav,你可以利用的环境完成简单到复杂的视觉语言导航,并有不同难度的指示,以及交流导航,机器人智能体可以在导航中寻求帮助。

▪视觉语言操作(Vision Language Manipulation):抓取是指机器人使用机械臂抓取物体并将其从一个原始位置移动到目标位置的动作。尽管机器人学习算法在现有的挑战上取得了很大的突破和改进,但仍有许多问题亟待解决。这项任务要求机器人按照视觉和语言的场景描述来抓取一个物体。虽然Saycan和RT-1在以前的研究中被用来实现使用Deep-RL算法的抓取,但这项任务更侧重于在现实环境中抓取薄、大、平、软的物体,避免碰撞,以及多任务抓取。参赛者需要根据大语言模型提供的指令,解决在不同场景下抓取不同物体的问题。具体抓取物品的技能需要参赛者基于提供的环境和工具接口,通过强化学习等方式进行训练。

1.2 评估

参赛队必须将LLMs纳入其机器人系统,以促进自然语言的理解和互动。比赛将根据以下标准来评估机器人系统的性能:

  • 任务完成的准确性和效率:参赛者将被评估任务完成的准确性和效率,包括物体操作、导航到准确位置的精度,执行推理速度,订单执行和人机互动。机器人必须准确、高效地完成任务,才能获得分数。

  • 人与机器人的互动:参赛者将被评估其机器人与顾客和工作人员互动的自然度和友好度。机器人必须以自然和友好的方式进行交流,以获得积分。

  • 时间限制:参赛者将有规定的时间来完成任务,在规定时间内得分最高的团队将被宣布为获胜者。

1.3 更多细节

需要这些团队在仿真咖啡厅场景中展开一场竞技,参赛者们
不仅要 “教” 服务机器人学会如何充当咖啡厅服务员的角色,还要应对顾客、老板等角色的多轮对话“考验”,
最终自主去执行完成一系列复杂任务。

人类充当服务员在咖啡店制作一杯咖啡,并将咖啡端到指定客户的桌上或许并非难事。但是如果换成机器人,其复杂度不言而喻。
这不仅仅面对硬件和环境的考验,还对于软件和算法提出了更大的挑战。

显著的技术融合性

为了实现高还原度,达闼首先在
仿真环境中构建了一个机器人元宇宙的数字孪生场景,
该虚拟场景是基于实际咖啡厅一致的各类数据产生,通过采集融合了几百个咖啡厅模型的各种常见物品,不仅仅还原了例如咖啡机、桌椅、饮品、蛋糕等环境中的各类物品、商品,同时还原了咖啡厅的实际布置灯光、清洁卫生用的工具等。一般团队很难有这个资金和精力。

值得注意的是,发现,该模拟环境中,甚至还考虑到了实际环境中物品的纹理和物理属性等问题,
杯子重量不同、落地会打碎,物品接触有摩擦力,
可以说基本做到了最终 100% 的还原。

通过提供庞大且还原度较高的数据集,基于这个数字孪生的场景,机器人开发平台
可以仅通过算力,就轻易且低成本在虚拟仿真中像在真实场景一样进行各种各样的训练
这也使得国内人工智能和智能大模型科研团队,能很快尝试在人形机器人上实现各类技术的结合落地。除了数字孪生环境,为了让机器人与环境进行交互的能力进一步提升,机器人硬件作为软件和算法的执行层,
其设计和能力也至关重要。
由于该机器人智能体需要与外界实现实时交互,这首先需要机器人对于环境实现感知,包括了听觉、视觉和触觉等方面。

例如人到了咖啡厅,机器人不仅需要领位,由于环境的还原度非常高,机器人制作咖啡的任务中,还需要再次细分,例如如何找到咖啡机的按钮,确定咖啡机的按钮和用途等。同时,在该任务中,选择咖啡、制作咖啡、运送咖啡等也都是难点。这意味着
如何通过大模型,实现对于实际环境任务的理解和分析并执行。
例如顾客对机器人说想要喝 XX 咖啡,这种任务可能就有所区别,首先需要依靠交流中大模型的分析,准确定义需求,并实现环境中的运动和操作能力。

多任务本质上就升级到了更高层的认知层面,需要机器人语言和视觉为主的大模型,
能在环境中实现感知、认知,并根据各种请求进行处理,
这就还涉及人工智能的算法,从而才能让机器人精准实现各种各样的操作。

大模型带来的变革

大模型对于实际场景的价值仍然处于发掘期,本次大赛中,大模型对于机器人技术的实际提升无疑是一个很大的亮点。
本次比赛着重体现了大模型技术应用思维链(CoT)能力的价值
该能力主要体现在机器人接到任务后,对于任务的分解,从而基于思维推理形成思路链,该方式相较原先的固定化编程和深度学习,机器人可以借助大语言模型,实现自然语言到机器语言的理解、转化,最终完成两者的对齐,从而自主化执行任务。这也意味着,机器人和大模型深度结合后,在未来如果进一步实现了
零样本学习 (zero-shot),
依托这两项技术,机器人也可以借助大模型实现关节运动控制,从而无需对机器人身体部位、动作的轨迹进行编程,真正做到零代码编程。

在这个比赛流程中,就看到了
智能服务机器人在语音、视觉、导航、操作等方面的落地可能性。
机器人进入陌生场景,首先会进行环境的主动探索与记忆,感知、判断不同物体和属性,实现记忆数据记录和调取。在此基础上,随后机器人开始在咖啡厅场景里与人进行交流对话,拆解任务信息。在执行层面,机器人需要借助视觉语言模型,拆分指令并实现具体动作,例如人说想喝水,机器人就需要拿取水杯、用水壶去倒水,并把水送给客人。

新任务新挑战

在该研究中,非常有意思的是达闼机器人还设计了两个具有挑战性的赛题,
在对话人员中加入了 “店长” 这一角色。
机器人除了需要作为服务员响应相关顾客的消费需求,还需要与店长 “对接” 工作,实现人机协同。

在店长与机器人的交互中,又衍生出了更加复杂的任务,机器人
需要完成 “领导交办的其他任务”。

“例如店长说好像地面不干净了,机器人就要理解这话什么意思,判断意思是我可能还要去再清洁一下卫生。”
类似的机器人触发式任务,非常考验机器人环境职责定义和自主动作选择,
需要最终机器人能够像是真正的咖啡厅服务人员,具备各种各样的附加能力,做到类似 “阴天开灯”、“水洒擦桌子” 等随机性事件的自主化观察和处理,为真正落地应用部署打下基础。

2. 项目安装(必看)

  • 技术简介:提出基于大模型和行为树的生成式具身智能体系统框架
    1. 行为树是系统的中枢,作为大模型和具身智能之间的桥梁,解决两者结合的挑战

    2. 大语言模型是系统的大脑。一方面,设计了向量数据库和工具调用,另一方面,在实现智能体规划上,不再需要大语言模型输出完整的动作序列,而仅仅给出一个任务目标,这大大缓解了大模型的具身幻觉现象。

    3. 而具身机器人是系统的躯体,在条件节点感知和动作节点控制的函数中,优化了接口调用和算法设计,提高感知高效性和控制准确性

2.1 环境要求

Python=3.10

2.2 安装步骤

git clone https://github.com/HPCL-EI/RoboWaiter.git
cd RoboWaiter
pip install -e .

以上步骤将完成robowaiter项目以及相关依赖库的安装

2.3 安装UI

  1. 安装
    graphviz-9.0.0
    (详见
    官网
    )

  2. 将软件安装目录的bin文件添加到系统环境中。如电脑是 Windows 系统,Graphviz 安装在 D:\Program Files (x86)\Graphviz2.38,该目录下有bin文件,将该路径添加到电脑系统环境变量 path 中,即 D:\Program Files (x86)\Graphviz2.38\bin。如果不行,则需要重启。

  3. 安装向量数据库
    conda install -c conda-forge faiss

  4. 安装自然语言处理和翻译工具,用于计算相似性

    pip install translate
    pip install spacy 
    python -m spacy download zh_core_web_lg
    

    zh_core_web_lg
    如果下载较慢,可以直接通过分享的网盘链接下载

    链接:
    https://pan.baidu.com/s/1vr7dqHsgnh6UChymQc26VA
    提取码:1201
    --来自百度网盘超级会员V7的分享

    pip install zh_core_web_lg-3.7.0-py3-none-any.whl
    

2.4 快速入门

  1. 安装 UE 及 Harix 插件,打开默认项目并运行

  2. 不使用 UI 界面 :运行 tasks_no_ui 文件夹下的任意场景即可实现机器人控制端与仿真器的交互

  3. 使用 UI 界面:运行
    run_ui.py
    ,显示下面的界面。点击左侧的按钮,机器人就会执行相应的任务。也可以在右上方直接输出目标状态或者对话和机器人直接交互。

3. 代码框架介绍

代码库被组织成几个模块,每个模块负责系统功能的一部分:

  • behavior_lib:
    behavior_lib
    是行为树节点库类,包括行为树的动作节点和条件节点。它们分别存放在
    act

    cond
    文件夹下。
  • behavior_tree:
    behavior_tree
    是行为树算法类,包括
    ptml
    编译器、最优行为树逆向扩展算法等。
  • robot:
    robot
    是机器人类,包括从
    ptml
    加载行为树的方法,以及执行行为树的方法等。
  • llm_client:
    llm_client
    是大模型类,主要实现了大模型的数据集构建、数据处理工具、大模型调用接口、大模型评测、工具调用、工具注册、向量数据库、单论对话、对轮对话等方法或接口。

​ 调用大模型接口。运行llm_client.py文件调用大模型进行多轮对话。输入字符即可等待回答/

cd robowaiter/llm_client
python multi_rounds.py
  • scene:
    scene
    是场景基类,该类实现了一些通用的场景操作接口,实现了与 UE 和咖啡厅仿真场景的通信。其中,包括了官方已经封装好的各种接口,如场景初始化、行人控制、操作动画设置、物品设置、机器人 IK 接口等。
    task_map
    返回的任务场景都继承于
    Scene
    。此外,在
    scene/ui
    中,实现了 UI 的界面设计和接口封装。
  • utils:
    utils
    为其它工具类,比如绘制行为树并输出为图片文件。
  • algos:
    algos
    是其它算法类,包括MemGPT、导航算法 (
    navigator
    )、边界探索 (
    explore
    )、视觉算法 (
    vision
    )、向量数据库 (
    retrieval
    ) 等。
  • tasks:
    tasks
    文件夹中存放的场景定义及运行代码。
缩写 任务
AEM 主动探索和记忆
GQA 具身多轮对话
VLN 视觉语言导航
VLM 视觉语言操作
OT 复杂开放任务
AT 自主任务
CafeDailyOperations 整体展示:咖啡厅的一天
Interact 命令行自由交互

4. 效果展示

机器人根据顾客的点单,完成订单并送餐

顾客询问物品位置,并要求机器人送回

资料下载

https://blog.csdn.net/sinat_39620217/article/details/136394954

更多优质内容请关注公号:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。

图神经网络基础理论及实操

推荐阅读:
1、
https://github.com/PacktPublishing/Hands-On-Graph-Neural-Networks-Using-Python
2、GAT:
http://arxiv.org/abs/1710.10903
3、GCN:
http://arxiv.org/abs/1609.02907
4、GraphSAGE:
http://arxiv.org/abs/1706.02216

任务经常加。。。
1、实操任务




2、GCN GAT等内容细节补充:





1、图神经网络基础知识

1.1 图基本理论

对于图神经网络的提出背景:常规算法(机器学习、卷积神经网络等)处理的大多为
欧几里得空间数据

Euclidean space
)[一般指:图片等数据]

欧几里德数据
:数据特点是排列整齐。对于某个节点,很容易可以找出其邻居节点,就在旁边,不偏不倚。最常见到的是图片(image)和视频(video)以及语音(voice)。
非欧几里德数据
:排列不整齐,比较的随意。具体体现在:对于数据中的某个点,难以定义出其邻居节点出来,或者是不同节点的邻居节点的数量是不同的。

但是对于一些
非欧几里得空间数据
(比如家族图谱、人物关系图谱等)对于传统神经网络来说几乎是处理不了的(换句话来说:世间万物之间都是彼此相互联系的,传统的深度学习、机器学习处理的都是单一,简单数据问题),因此提出
图神经网络

\(Graph \quad Neural \quad Network\)

欧几里得空间和非欧几里得空间下示意图


对于一组图定义为:
\(G=(V,E,R,T)\)
其中:1、节点:
\(v_i \in V\)
;2、不同节点之间联系:
\((v_i, r, v_j)\)
;3、节点之间相关性:
\(r \in R\)
;4、节点类型:
\(T(v_i)\)
。简单上理解一幅“图”就是若干个节点在若干节点之间彼此联系(连接| 联系类型分为:有向、无向、权重、自循环等)。

比如说:

20240229101609

在上图中有3个人(A、B、C 紫色代表男生)彼此之间是联系的,并且我们定义各自的特征:
V1、V2
(比如说生高、体重)。比如我们在做节点分类任务时候,就需要根据其特征进行分类。

代码示例
from torch_geometric.data import Data
import torch
x = torch.Tensor([[185, 75], [160, 65], [192,80]])
edge_index = torch.Tensor(
   [[0,0,1,1,2,2],
   [1,2,0,2,0,1]]
)
y = torch.Tensor([[0, 0], [1, 0], [2, 1]])
data = Data(x= x, edge_index= edge_index, y= y)
print(f'点的数量: {data.num_nodes}')
print(f'边的数量: {int(data.num_edges/2)}')
print(f'节点特征维度: {data.num_edges / data.num_nodes:.2f}')   #2E/N 
# print(f'训练节点数量: {data.train_mask.sum()}')
# print(f'训练节点比率: {int(data.train_mask.sum()) / data.num_nodes:.2f}')
print(f'包含孤立节点: {data.contains_isolated_nodes()}')
print(f'包含自循环: {data.contains_self_loops()}')
print(f'是否为无向图: {data.is_undirected()}')

点的数量: 3
边的数量: 3
节点特征维度: 2.00
包含孤立节点: False
包含自循环: False
是否为无向图: True

便于数学上理解将一幅图(定义比较宽泛:可以是人物关系图谱、图片像素联系等)转化成一组
邻接矩阵
(Adjacency Matrices)

更加简单定义:
\(G=(V,E)\)
其中:
\(V\)
代表图中的节点;
\(E\)
代表不同节点之间的边(点之间权重、有向/无向);

邻接矩阵对一幅图的描述

对于

的生成上借助
networkx
[1]
进行操作:

  • 1、定义图(有向/无向)
定义图代码示例
import networkx as nx
G1 = nx.Graph() # 定义有向图
G2 = nx.DiGraph() # 定义无向图
"""
可以直接对数组等进行操作
a=np.random.randint(0,2,size=(5,5))   #产生5行5列的随机整矩阵,因为要生成图,所以必须是方阵
G=nx.DiGraph(a)
"""
  • 2、添加/删除

    如果需要设置权重,只需要在定义边时,添加
    {参数说明: 参数值}
    这样一来所有的边与边之间都会使用
    参数说明
    (如:
    {"color":"red"}
    )
边操作代码示例
G1.add_edges_from([('A', 'B'), ('C','D'), ('B', 'C')])
G1.remove_edges_from([("A", "B")])
"""
G1.remove_edge("A", "B")
"""
G1.add_edges_from([('A', 'B', {"weight": 10}), ('C','D',{"weight": 10})])
# nx.get_edge_attributes(G2, "weight") 即可访问参数weights
# G1.edges() 访问边之间联系
  • 3、添加/删除
点操作代码示例
G1.add_node("spam") 


基础理论:

1、邻接矩阵
\(A\)

\[A_{i,j}=\begin{cases}
1 \qquad 如果i,j之间存在边\\
0
\end{cases}
\]

2、度矩阵
\(D\)

\[D_{i,j}=\begin{cases}
deg(v_i)\qquad 如果i=j\\
0
\end{cases}
\]

也就是说计算与节点
\(i\)
连接的边的个数

\(D^{- 1/2}\)
相当于对于每一个元素
开根号

无向图、邻接矩阵、度矩阵三者示意图
图转化为矩阵代码示例
nx.to_numpy_array(G1)
networkx操作补充

1、访问指定节点的邻居节点:
G.neighbors(node)

0### 1.2 图embedding方法

1.2.1
DeepWalk
算法
[2]
[3]

将自然语言处理的算法(work2vec
[4]
)引入到图神经网络中来。word2vec通过语料库中的句子序列来描述词与词的共现关系,进而学习到词语的向量表示。DeepWalk算法与word2vec类似,
使用图中节点与节点的共现关系来学习节点的向量表示
。在DeepWalk中通过使用随机游走(RandomWalk: 从图中随机选择节点)的方式在图中进行节点采样来模拟语料库中的预料,进而使用word2vec的方式学习出节点的共现关系
[5]

DeepWalk
在算法上首先通过随机游走采样节点序列,而后使用skip-gram model学习表达向量。

skip-gram
介绍
在论文中,作者介绍了两个结构
CBOW
以及
skip-gram

20240226170142

skip-gram
从当前位置词去预测前后的词,比如说::
我叫小明
,选择参数
(input word, skip window, window size)
,(设置
skip window=1, window size=2
,也就是说对于
input word
我们去访问其前后“窗口”
1
个词,
window size
那么就将
input word
与开始选择的“窗口”中的词进行组合, 选择出2个词)那么在获取第一个词

的时候,其“窗口”为:
我叫
(因为前面没有词)那么得到为(
我叫

20240226171447

1.2.2
node2vec

2、基本图神经网络

2.1 图卷积神经网络

沿用论文
[6]
中对图神经网络的定义:

\[f(X,A)= \sigma(D^{- 1/2}(A+I)D^{- 1/2}XW)
\]

其中:

\[A:邻接矩阵(n*n),I:单位矩阵(n*n),D:度矩阵(n*n),\\ X:输入数据(n*d),W:权重参数(d*w), \sigma():激活函数
\]

从函数定义上,和一般的神经网络
很相似
:设计一个网络结构(就是我们的参数
\(W\)
),输出数据然后通过优化算法去对参数进行优化。

  • 1、
    \(A+I\)
    理解

我们知道在一组图(社交网络等)中
节点之间彼此联系
,并且
节点自身具有特性

那么就需要对两个都进行考虑
),那么在构建模型过程中需要保证
对于节点自身以及节点之间信息
进行充分考虑(亦或者说:对
信息进行传递
)。正如上面(图的定义)所提到的,我们需要把一组图转化为一个
邻接矩阵
\(A\)
对其进行数学表示,而后将得到的邻接矩阵和
\(XW\)
就行相乘,这样一来就考虑到了节点之间联系了。但是为什么不将函数设计成(
VanillaGNN
):

\[f(X,A)= \sigma(AXW) \tag{1}
\]

给出了解释
[7]
[8]

  • 1、没有考虑到自身节点信息自传递的问题;
  • 2、
    \(A\)
    通常未标准化,因此与
    \(A\)
    相乘将完全改变特征向量的尺度
  • 更加直观的解释:比如说节点A有1000个邻居节点,而节点B只有1个邻居节点,这样一来计算得到的值之间差距就较大。

所以对于邻接矩阵(
\(A\)
)加上单位矩阵(
\(I\)
)就相当于在图中添加一个自循环

  • 2、
    \(D^{- 1/2}(A+I)D^{- 1/2}\)
    的理解

对于
\(D^{- 1/2}(A+I)D^{- 1/2}\)
被称为:
normalize the adjacency matrix

为什么要执行
标准化
?为什么不直接用

\[f(X,A)= \sigma(DAXW) \tag{2}
\]

回顾图的定义:一组图由两部分构成点和边(以节点分类任务为例);对于结点
\(i\)
我们需要通过结合与节点
\(i\)
相连接的其它节点和他们之间的边的信息来对
\(i\)
进行判断。那么也就是说我们要
首先对邻接节点信息进行汇聚

Aggregate information
)而后后续操作。既然要对对数据进行汇聚,那么问题来了:在图中有些结点与其它节点之间存在较多连接,而有些节点可能就只有一个节点和他连接。

如果直接用公式
\((2)\)
这样虽然考虑到节点之间信息但是在后续对于参数优化上就会造成困难,所以一个最直接的例子就是:
既然连接点数量之间存在差异,那么我直接去除以你的节点个数!!

2.1.1 卷积图神经网络理解

对上述公式
\(f(X,A)= \sigma(D^{- 1/2}(A+I)D^{- 1/2}XW)\)
将其简化为
\(f(X,A)=\sigma(\widehat{A}XW)\)
借用如下图
[9]
理解图卷积算法(其中
\(H\)
对应上述公式中的
\(X\)
)

https://blog.csdn.net/zbp_12138/article/details/110246797

回顾简化的图卷积函数(
\(f(X,A)=\sigma(\widehat{A}XW)\)
),图卷积网络在设计上借鉴了卷积神经网络,矩阵
\(\widehat{A}\)
中存在许多0也就是说,我们可以通过对于某个节点设计一个 “卷积核” ,去对与之相连接的节点进行“卷积运算”而后进行“池化”操作

https://mbernste.github.io/posts/gcn/

2.1.2 GCN代码

from torch_geometric.nn import GCNConv
import torch.nn.functional as F

# 实现形式1
class GCN(nn.Module):
    def __init__(self, input_dim: int, class_label: int):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(input_dim, 16)
        self.conv2 = GCNConv(16, class_label)

    def forward(self, data):
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        output = self.conv2(x, edge_index)

        return output

# GCN定义
from dgl.nn import GraphConv
class GCN(nn.Module):
    def __init__(self, in_feats, h_feats, num_classes) -> None:
        super(GCN, self).__init__()
        self.conv1 = GraphConv(in_feats, h_feats)
        self.conv2 = GraphConv(h_feats, num_classes)
    
    def forward(self, g, in_feats):
        h = self.conv1(g, in_feats)
        h = F.relu(h)
        h = self.conv2(g, h)
        return h

参考:
1、
http://arxiv.org/abs/1609.02907
2、
https://mbernste.github.io/posts/gcn/
3、
https://zhuanlan.zhihu.com/p/89503068
4、
https://blog.csdn.net/zbp_12138/article/details/110246797


2.2 图注意力网络 GAT

GAT网络特征:

  • 1、可以跨越节点就行并行化操作
  • 2、它可以通过为邻居节点
    指定任意权重
    ,应用于具有不同度的图节点

此处区别GCN,GCN是直接计算
邻居节点的平均
(权重是恒定的)

  • 3、该模型直接适用于
    归纳学习问题
    ,包括模型必须泛化到
    完全看不见的图形的任务

Global graph attention
[10]

就是每一个顶点
\(i\)
都对于图上任意顶点都进行
attention
运算。完全不依赖于图的结构,可能造成:(1)丢掉了图结构的这个特征,效果可能会很差(2)运算面临着高昂的成本

(1) the operation is efficient, since it is parallelizable across nodeneighbor pairs;
(2) it can be applied to graph nodes having different degrees by specifying arbitrary weights to the neighbors;
(3) the model is directly applicable to inductive learning problems, including tasks where the model has to generalize to completely unseen graphs.

2.2.1 GAT网络定义

论文
[11]
中定义:输入一系列节点特征
\(h=\{\vec{h_1},...,\vec{h_N} \}\)
其中
\(\vec{h_i} \in R^F\)

\(N\)
代表节点的数量,
\(F\)
代表每一个节点特征数量。GAT算法步骤

  • 第一步
    :对于每一个节点添加一个共享线性映射

\[(W\vec{h_i}||W\vec{h_j})
\]

其中
\(W\in R^{{F^ \prime}*F}\)
,通过计算进而对顶点特征就行增维,
\(||\)
去对特征就行拼接(axis=1)

  • 第二步
    :对于线性映射的节点添加
    注意力机制
    (self-attention)

\[e_{ij}=a(W\vec{h_i}|| W\vec{h_j})
\]

其中
\(e_{ij}\)
代表
注意力系数
用来计算节点
\(i\)
邻居节点
\(j\)
对其的重要性,
\(a\)
是一层
前馈神经网络
。这样一来模型允许每个节点参与到其它节点上,进而省去了所有的结构信息,并且使用
\(LeakyReLU\)
作为激活函数。

masked attention
we only compute eij for nodes j ∈ Ni, where Ni is some neighborhood of node i in the graph.
也就是说对于节点
\(i\)
只计算与之相联系的节点

此处也印证了GAT的特征3
,对于
inductive learning problems
,在GAT中去改变网络结构无非就是改变
\(N_i\)

  • 第三步
    :添加激活函数以及计算
    \(softmax\)

\[\begin{aligned}
\alpha_{ij}&= softmax(e_{ij})= \frac{exp(e_{ij})}{\sum_{k\in N_i}exp(e_{ik})}\\
&=\frac{exp(LeakyReLU(\vec{a^T}[W\vec{h_i ||W\vec{h_j}}]))}{\sum_{k\in N_i}exp(LeakyReLU(\vec{a^T}[W\vec{h_i ||W\vec{h_k}}]))}
\end{aligned}
\]

其中
\(T\)
代表转置,
\(||\)
代表串联操作

  • 第四步
    :多头注意力处理

\[单头注意力: \vec{h}_i^{\prime}=\sigma\left(\sum_{j\in N_i}\alpha_{ij}\mathbf{W}\vec{h}_j\right)
\]

其中
\(\sigma\)
代表非线性激活。对于多头注意力:

\[\\
concat: \vec{h}_i^{\prime}= ||_{k=1}^{K} \sigma\left(\sum_{j\in N_i}\alpha_{ij}^{k}\mathbf{W^k}\vec{h}_j\right) \\
avg: \vec{h}_i^{\prime}= \sigma\left(\frac{1}{K} \sum_{k=1}^K \sum_{j\in N_i}\alpha_{ij}^{k}\mathbf{W^k}\vec{h}_j\right)
\]

算法流程图:

GAT流程图$

对于上图左半部分(
注意力机制
)很好理解:就相当于对节点做一个矩阵相乘(
\(W\)
),而后通过前馈神经网络(
\(LeakyReLU\)

\(softmax\)
)进行处理得到
\(\alpha_{ij}\)
。对于右半部分:对于节点
\(\vec{h_1}\)
假设6个节点与其联系。对于每一个联系节点通过
3
层(上述图中3中颜色)
注意力
进行处理。对后续结果进行
拼接/平均

\(concat/avg\)
)得到
\(\vec{h_1^·}\)

代码解释上述过程(以如下网络为例)

20240227190054

那么可以定义我们如下数据
图A
数据
X

import numpy as np 
np.random.seed(0) 
A = np.array([[1, 1, 1, 1], [1, 1, 0, 0], [1, 0, 1, 1], [1, 0, 1, 1] ])
X = np.random.uniform(-1, 1, (4,4))

那么计算
\(e_{ij}=a(W\vec{h_i}|| W\vec{h_j})\)

\(a\)
代表前馈神经网络)这样一来就需要定义两个参数:

W = np.random.uniform(-1,1, (4,4)) # 内部矩阵乘法
W_att = np.random.uniform(-1, 1, (4,4)) #外层的前馈神经网络

connections = np.where(A>0) # 这样一来就可以知道那些点之间是连接的
"""
输出:
(array([0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3]),
 array([0, 1, 2, 3, 0, 1, 0, 2, 3, 0, 2, 3]))
 代表(0,0) (0,1) (0,2), (0,3)是连接的
"""
a = W_att@ np.concatenate([(X@W.T)[connections[0]], (X@ W.T)[connections[1]]], axis=1).T

计算
\(\alpha_{ij}=\frac{exp(LeakyReLU(\vec{a^T}[W\vec{h_i ||W\vec{h_j}}]))}{\sum_{k\in N_i}exp(LeakyReLU(\vec{a^T}[W\vec{h_i ||W\vec{h_k}}]))}\)

def leaky_relu(x, alpha=0.2):
    return np.maximum(alpha*x, x)
def softmax2D(x, axis): 
    e = np.exp(x - np.expand_dims(np.max(x, axis=axis), axis)) 
    sum = np.expand_dims(np.sum(e, axis=axis), axis) 
    return e / sum 
e = leaky_relu(a)
E = np.zeros(A.shape)
E[connections[0], connections[1]] = e[0]
W_alpha = softmax2D(E, 1)

最后计算$\vec{h}
i^{\prime}=\sigma\left(\sum
\alpha_{ij}\mathbf{W}\vec{h}_j\right) $:

H = A.T @ W_alpha @ X @ W.T

对于多头注意力只需要重复设置
W,W_att
即可

3.其他图神经网络结构

3.1 STGNN(Spatio-Temporal Graph Convolutional Networks)

作者
[12]
在处理交通网络预测过程中出现:交通流的非线性以及复杂性,不是借助传统的
卷积单元

循环单元
而是通过图神经网络进行处理。并且提出
时空图卷积网络(STGNN)
作者对于交通预测描述如下:

\[\widehat{v}_{t+1},...,\widehat{v}_{t+H}= \quad \underset{v_{t+1}, \ldots, v_{t+H}}{\arg \max } \log P\left(v_{t+1}, \ldots, v_{t+H} \mid v_{t-M+1}, \ldots, v_{t}\right),
\]

也就是说:根据
\(M\)
个过去时间节点数据预测未来
\(H\)
时刻数据,其中
\(v_t \in R^n\)
代表在
\(n\)
条道路在时间
\(t\)
下的观察向量(记录道路的流量)

交通数据描述

因此作者将上述结构定义如下图神经网络:$G_t= (V_t, \varepsilon, w) $分别代表有限节点集合、边、权重。

3.1.1 网络结构

STGNN网络结构(自左向右)

输入数据(
\(V_{t-M+1},...,V_t\)
)而后通过
两层ST-Conv Blovk
以及
全连接层
进行预测输出。
ST-Conv Block结构
(中间部分)包含两个
时间门控卷积层(Temporal Gated-Conv)
,中间包含一个
空间图形卷积层(Spatial Graph-Conv)
。在每个块内部应用了残差连接和瓶颈策略。

  • ST-Conv Block

ST-Conv Block结构由:
Temporal Gated-Conv(TGC)
+
Spatial Graph-Conv(SGC)
+
Temporal Gated-Conv
,对于此类结构作者给出的解释:可以通过时间卷积实现从图卷积到空间状态的快速传播。"三明治"结构还帮助网络充分运用
瓶颈策略
,通过图卷积层对通道C进行降尺度和升尺度处理,实现尺度压缩和特征压缩。此外,在每个ST-Conv块中使用层归一化来防止过拟合

Can achieve fast spatial-state propagation from graph convolution through temporal convolutions. The “sandwich” structure also helps the network sufficiently apply bottleneck strategy to achieve scale compression and feature squeezing by downscaling and upscaling of channels C through the graph convolutional layer. Moreover, layer normalization is utilized within every ST-Conv block to prevent overfitting

  • Temporal Gated-Conv(TGC)

对于TGC通过
1-D casual convolution

gated linear units(GLU [13]
构成

Temporal Gated-Conv(TGC)结构

参考
1、
http://arxiv.org/abs/1709.04875
2、
https://zhuanlan.zhihu.com/p/286445515

3.2
G
ated
G
raph
S
equence
N
eural
N
etwork
[14]

从名字上很好理解,
\(GGSNN\)

门控序列图神经网络
)是作为一种可以对序列进行预测的图神经网络,作者提到该网络添加:
1、门控序列单元
(gated recurrent units);
2、“优化”方法
(modern optimization techniques)

  • 1、门控图神经网络
    (Gated Graph Neural Network)

3.3 GraphSAGE

GrapgSAGE
一种处理大规模图的GNN结构,它利用节点特征信息(例如文本属性)来高效生成
先前未见数据
的节点嵌入。相较之之前的神经网络结构对于生成节点嵌入本质上是传导性,方法上也都基于矩阵分解。
[15]

20240228091719
  • 1、前向传播算法(forward propagation algorithm)
前向传播算法

从伪代码上很好理解,上述参数中:K:网络的层数,也代表着每个顶点能够聚合的邻接点的跳数。算法步骤:在每一层的循环k中,对每个顶点v,首先便用 v 的邻接点的k-1层的embedding表示
\(h_u^{k-1}\)
其临近顶点的第k层
聚合表示
\(h_{N(v)}^k\)
,之后将
\(h_{N(v)}^k\)
和顶点
\(v\)
的第
\(k-1\)
层表示
\(h_u^{k-1}\)
一个
非线性变换
产生顶点
\(v\)
的第
\(k\)
层embedding表示
\(h_v^k\)
。进行拼接,经过一个非线性变换产生顶点v的第k层embedding表示
\(h_v^k\)

比如说在
\(k=1\)
时并不是将其所有的联系节点信息进行聚合,而是通过采样之后再去汇聚

  • 2、聚合结构(Aggregator Architecture)

聚合结构就和卷积神经网络中的池化层一样,对于节点
\(h_v^0\)

\(K=k\)
与之连接的节点信息进行“聚合”。在论文中提供了:
1、
Mean aggregator

\(\mathbf{h}_v^k\leftarrow\sigma(\mathbf{W}\cdot\text{мЕА}\mathbf{N}(\{\mathbf{h}_v^{k-1}\}\cup\{\mathbf{h}_u^{k-1},\forall u\in\mathcal{N}(v)\}).\)

2、
LSTM aggregator
:较之方法1表达能力更强;
3、
Pooling aggregator
:同时考虑对称性和可训练性。
\(\text{AGGREGATE}_k^{\mathbf{pool}}=\max(\left\{\sigma\left(\mathbf{W}_{\mathrm{pool}}\mathbf{h}_{u_i}^{k}+\mathbf{b}\right),\forall u_i\in\mathcal{N}(v)\right\}),\)

3、GNN实操

3.1 节点分类
[3:1]

大家好,我是知微!

作为程序员,不论是开发还是学习,肯定会用到开源项目,那么怎么快速在开源网站找到这些项目呢?

  • 常用的开源网站有:github 和 gitee

  • github是全球最大的开源社区,今天就以github为例,演示一下

  • github界面

  • 一般来说,优秀的项目,维护会比较频繁,提交数也就会多一点。当然,一个好的项目,它的
    Star
    数和
    Fork
    数也会比较多。

普通人搜索的方式

1、打开
github

2、输入关键词,搜出来一堆的项目,随便浏览一下,简单看一下README文档。嗯,感觉还不错的样子!

3、然后就是克隆仓库,看一下源码,发现看不懂,内心OS:这是给人看的吗?删了删了!

心累

用这种方法想要找到适合自己的开源项目,跟大海捞针没什么区别。只会一次次的浪费时间,也会消耗自己的耐心和精力,到最后干脆摆烂躺平了。

不过在看这篇文章的你,肯定不想这样啦!那么下面的10个
github
高级搜索技巧,赶紧学起来吧!

10个高级搜索技巧

⑴、通过
in
关键词搜索

in关键词可以用来限制搜索范围
,精准搜索仓库名称name,说明description 以及README 文件中的内容。description 就是github界面图中, About 中的信息。

示例 说明
in:name C++ 搜索项目名称中包含 "C++" 的所有项目
in:description machine learning 搜索项目描述中包含 "machine learning" 的所有项目
in:readme API 搜索项目介绍文档(README)中包含 "API" 的所有项目

下面以搜索
spring boot
相关的项目为例:

  • 如果直接在搜索栏输入
    spring boot
    并回车,会搜到46w个结果

  • 做一个限制,这次搜索项目名里含有 spring boot 的


    in:name spring boot

​ 看到没有,数量马上又46w降到29.5w,但是项目数量还是太多了。没关系,我们可以再加其他的搜索限制,接着往下看!

⑵、通过 stars、forks 数量搜索

一个优秀的项目 star 数量和 fork 数量肯定不会少,那么我可以使用
大于
某个数,或者
在某个范围之间
的方式来过滤项目:

  1. 按照星标数量搜索:
    • 语法:
      关键字 stars:>=数量

      关键字 stars:数量1..数量2
  2. 按照分支数量搜索:
    • 语法:
      关键字 forks:>=数量

      关键字 forks:数量1..数量2
示例 说明
javascript stars:>1000 搜索所有星标数量大于1000JavaScript项目
javascript stars:1000..2000 搜索所有星标数量在1000到2000之间的JavaScript项目
web framework forks:>500 搜索所有分支数量大于500的 Web 框架项目
web framework forks:500..1000 搜索所有分支数量在500到1000之间的 Web 框架项目
  • 我们进一步限制搜索范围,要求star数量大于2000,数量马上变成只有31个


    in:name spring boot starts:>2000


    stars大于2000

  • 再要求fork数量大于1000,满足要求的项目数量更少了,只有19个


    in:name spring boot starts:>2000 forks:>1000

⑶、按项目创建时间、更新时间搜索

如果优秀项目比较多,相信大家都会喜欢最新的项目,那么就可以把老旧的项目筛选出去。

要是本来就没几个项目供你选,就没必要做这一步了。

  1. 按照项目创建时间搜索:
    • 语法:
      关键字 created:>=日期
  2. 按照项目更新时间搜索:
    • 语法:
      关键字 pushed:>=日期
示例 说明
java created:>=2022-01-01 搜索在2022年1月1日之后创建的Java项目
android pushed:>=2022-01-01 搜索在2022年1月1日之后更新的Android项目
  • 演示:

pushed

⑷、按照地区、编程语言搜索

  • 一般我们都是想找到自己会的编程语言写的项目,否则还得专门去学一遍语言才能看懂,那岂不是兜了一大圈。

  • 另外,要是项目有中文的文档说明,就更好了!(虽然很多优秀的项目都是用英文写的,程序员不能排斥学习英语呀!)

  1. 按照地区搜索:
    • 语法:
      location:地区 关键字
  2. 按照编程语言搜索:
    • 语法:
      language:编程语言 关键字
示例 说明
location:china 地区为中国
language:python 编程语言为python
  • 例如使用 python 编程语言,且star数量大于1000的国产项目,搜索条件就是:location:china language:python stars:>1000

⑸、按文件名、仓库大小、扩展名搜索

  • 凡事都是从易到难,一开始我们更倾向于找一些小型的项目来学习,那么可以用
    size
    来筛选一些简单点的项目。
  1. 按照文件名搜索:
    • 语法:
      关键字 filename:文件名
  2. 按照仓库大小搜索:
    • 语法:
      关键字 size:>=大小
  3. 按照扩展名搜索:
    • 语法:
      关键字 extension:扩展名
示例 说明
machine learning filename:utils 搜索包含文件名为
utils
的机器学习项目
data analysis size:<5000 搜索仓库小于5000KB的数据分析项目(默认单位 KB)
web development extension:html 搜索包含HTML文件的 web development 项目
  • 举个例子:
    data analysis size:<5000 extension:py

⑹、按文件、路径内容搜索

  1. 按照文件内容搜索:


    • 语法:
      关键字 in:file 搜索内容
  2. 按照路径内容搜索:


    • 语法:
      关键字 path:路径/to/search
示例 说明
machine learning in:file 包含 "machine learning" 内容的所有文件
database path:src/ 搜索在路径为
src/
下的所有文件中包含关键字 "database" 的项目

例子:
假设你想要查找包含 "authentication" 内容的文件,并且这些文件位于名为
src/
的路径下,你可以使用如下搜索条件

  • authentication in:file path:src/

文件名,路径搜索

⑺、根据某个人或组织进行搜索

  • 这个可以用来精准搜索你关注的大神是不是提交了新的项目
  1. 搜索特定个人的项目:
    • 语法:
      user:用户名 关键字
  2. 搜索特定组织的项目:
    • 语法:
      org:组织名 关键字
示例 说明
user:torvalds linux kernel 搜索用户 Linus Torvalds 的项目中包含 "linux kernel" 的内容
org:Microsoft azure cloud 搜索 Microsoft 组织的项目中包含 "azure cloud" 的内容

torvalds

⑻、根据仓库的LICENSE搜索

在使用任何开源项目之前,最好详细阅读并理解项目所采用的具体授权协议,因为有的开源项目作者是明确禁止商用的,如果你使用在商业上,后面会很麻烦的!

按照许可证搜索:

  • 语法:
    license:许可证类型 关键字
示例 说明
license:gpl encryption 搜索包含GPL许可证的仓库中含有 "encryption" 关键字的项目

⑼、awesome加强搜索

  • awesome
    往往整合了大量的同一领域的资料,收集学习、工具、书籍类相关的项目,方便大家更好的学习。

  • 比如搜索优秀的java相关的项目,包括框架、教程等

awesome java

⑽、热门搜索(GitHub Trend 和 GitHub Topic)

  • GitHub Trend 允许你查看当前在 GitHub 上受欢迎的项目,根据不同的编程语言和时间范围进行筛选

  • GitHub Topic 是一种对项目进行标签分类的方式。GitHub 上的项目可以被分配到不同的主题标签,使得你可以通过主题来浏览和发现项目。

以上就是关于高效寻找开源项目的全部内容了!

一、背景

前几天下午飞书告警群里报起了
java.lang.OutOfMemoryError: unable to create new native thread
告警,看见后艾特了对应的项目负责人但是负责人说没时间,无奈自己亲自上阵。

二、事情经过

2.1 问题排查

从报错信息就可以看出是服务申请不到足够的内存去创建新的线程导致的,熟悉JVM的都知道线程用的是虚拟机栈内存,这里是虚拟机栈内存不够跟堆没有关系。

然后立马登录阿里云进入容器使用如下命令dump出线程堆栈

jstack -l 1 > dump.log

让运维帮我把文件下载下来后,就把dump.log上传到网站
https://fastthread.io/
进行分析,分析结果如下:

线程总览

可以看到服务的线程数竟然高达2000多个!!!而且也给出来警告这么高的线程数可能导致OOM,那么问题原因就很清楚了就是线程数过多导致的,那么是哪些线程过多呢?

线程数量排行


第二张图显示数量做多的是名字为
com.alibaba.nacos.client.Worker
的线程,并且排行前三名都是nacos的线程,我一度怀疑是nacos出bug了