TowardsDataScience 2023 博客中文翻译(六十五)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

使用 LangChain 和 LLMs 的业务分析

原文:towardsdatascience.com/business-analytics-with-langchain-and-llms-c8e902446073

生成式 AI

一个关于用人类语言查询 SQL 数据库的分步教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Naser Tamimi

·发表于 数据科学前沿 ·7 分钟阅读·2023 年 12 月 19 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供(通过 Midjourney 生成)

许多企业在其数据库中存储了大量专有数据。如果有一个能够理解人类语言并查询这些数据库的虚拟代理,这将为这些企业打开巨大的机会。想想客户服务聊天机器人,它们就是一个常见的例子。这些代理可以接受客户请求,向数据库询问信息,并向客户提供他们所需的内容。

这些代理的好处不仅限于外部客户互动。许多企业主或公司中的人员,即使是在科技公司,也可能不知道 SQL 或类似的语言,但他们仍然需要向数据库查询信息。这就是像 LangChain 这样的框架派上用场的地方。这些框架使得创建这些有用的代理/应用程序变得容易。那些可以与人类对话,同时与数据库、API 等进行交互的代理。

LLM 支持的应用程序

LangChain 是一个开源框架,用于构建使用大型语言模型(LLMs)的互动应用程序。这是一个帮助 LLMs 连接其他信息来源,并使其能够与周围世界对话的工具。在这些框架中,一个重要的概念是链(Chain)。让我们来看看这个概念。

什么是链(Chains)?

链接是这个框架中的高级工具,它们将 LLM 与其他工具结合起来,以执行更复杂的任务。具体来说,链是使用 LLM 序列和其他工具(如 SQL 数据库、API 调用、bash 操作符或数学计算器)来完成复杂工作的接口。例如,我们的应用程序接收来自用户的输入并将其传递给我们的 LLM 模型;然后,LLM 调用一个 API。API 对 LLM 进行响应,LLM 使用响应执行另一个任务,如此循环往复。正如你所看到的,这是一系列输入和输出的链条,其中在许多部分,我们有 LLM 模型处理情况。

开始动手实践

现在是时候开始动手编写一个简单的 LLM 支持的应用程序了。对于这个应用程序,我们将制作一个简单的问答代理,它接收我们的问题并查询 SQL 数据库以为我们找到答案。

设置 PostgreSQL 示例数据库

我们使用了来自 postgresqltutorial.com 的 DVD Rental Sample Database许可证信息)。要在你的本地系统上安装数据库,你需要安装 PostgreSQL。在终端中简单地输入 *psql* 看看它是否运行。

然后你应该按照 这里 的说明进行操作。这里我将快速带你完成数据库安装过程。

在你的终端中通过以下命令启动 PostgreSQL:

psql -U <USERNAME>

你必须将 <USERNAME> 替换为你的实际用户名。系统会询问你的密码。输入你的密码后,你将进入你的 Postgres 数据库。

首先,我们应该创建一个数据库以加载所有的表。

postgres=# CREATE DATABASE dvdrental;

创建数据库后,你可以通过输入 *\list* 命令来检查它,你应该会在返回的列表中看到你的 dvdrental 数据库。然后简单地退出 Postgres(通过 \q)。

现在我们需要下载表和数据。你可以在这里下载所有内容的 tar 文件:下载 DVD Rental Sample Database

进入你下载 tar 文件的文件夹,使用 pg_restore,我们可以将表加载到我们的 Postgres 数据库中。

pg_restore -U postgres -d dvdrental dvdrental.tar

在继续之前,让我们检查表是否已加载。通过 psql -U <USERNAME> 启动 Postgres 并输入你的密码。

然后输入以下命令以列出 dvdrental 数据库中的表。

postgres=# \c dvdrental
dvdrental=# \dt

你应该看到一个如下所示的表列表:

 List of relations
 Schema |     Name      | Type  |  Owner
--------+---------------+-------+----------
 public | actor         | table | postgres
 public | address       | table | postgres
 public | category      | table | postgres
 public | city          | table | postgres
 public | country       | table | postgres
 public | customer      | table | postgres
 public | film          | table | postgres
 public | film_actor    | table | postgres
 public | film_category | table | postgres
 public | inventory     | table | postgres
 public | language      | table | postgres
 public | payment       | table | postgres
 public | rental        | table | postgres
 public | staff         | table | postgres
 public | store         | table | postgres

设置 .env 文件

在构建示例数据库之后,我们需要创建一个 .env 文件。我们使用此文件来存储我们的秘密、密钥以及环境变量。当然,我们可以将所有这些信息放在代码中,但即使是小项目也必须遵循最佳工程实践。意外的 git push 可能会将我们的 API 密钥和秘密暴露给公众。以下是我们的 .env 文件:

OPENAI_API_KEY = 'YOUR-OPENAI-API-KEY'
PSQL_HOST = 'localhost'
PSQL_PORT = 'YOUR-POSTGRES-PORT'
PSQL_USERNAME = 'YOUR-POSTGRES-USERNAME'
PSQL_PASSWORD = 'YOUR-POSTGRES-PASSWORD'
PSQL_DB = 'dvdrental'

正如你所见,你需要获得自己的 OpenAI API 密钥进行测试。你可以按照 这里 的说明从 Open AI 获取 API 密钥。

创建一个 LangChain 应用程序

在将 .env 文件保存到你的项目文件夹后,我们可以开始实际的代码。首先,我们将所需的库导入到 Python 代码中。

pip install langchain langchain-experimental openai psycopg2

对于本教程,我建议使用 Jupyter Notebook 逐步测试它。

我们需要在开始时导入所需的库。

from os import environ
from dotenv import load_dotenv

from langchain.chat_models import ChatOpenAI
from langchain.utilities import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain

load_dotenv()

使用 load_dotenv(),我们加载了在 .env 文件中定义的环境变量。现在,我们可以安全地在代码中访问它们。

对于我们的链,我们需要一个具有聊天功能的语言模型。为简单起见,我们选择了来自 OpenAI 的 gpt-3.5-turbo,该模型可以通过 API 访问。你可以使用任何其他公共或私有模型。

# Instantiating Our LLM

OPENAI_API_KEY = environ.get("OPENAI_API_KEY")
llm = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0, openai_api_key=OPENAI_API_KEY)

除了模型,我们还需要一个 SQL 数据库连接。该连接使我们的链能够对数据库进行查询并获取结果。如前所述,我们使用的是 PostgreSQL 数据库,但根据 LangChain 的说法,任何具有 JDBC 连接的 SQL 引擎都应该容易使用(例如 MySQL、Presto、Databricks)。

# Database Setup

PSQL_HOST = environ.get("PSQL_HOST")
PSQL_PORT = environ.get("PSQL_PORT")
PSQL_USERNAME = environ.get("PSQL_USERNAME")
PSQL_PASSWORD = environ.get("PSQL_PASSWORD")
PSQL_DB = environ.get("PSQL_DB")
psql_uri = f"postgresql+psycopg2://{PSQL_USERNAME}:{PSQL_PASSWORD}@{PSQL_HOST}:{PSQL_PORT}/{PSQL_DB}"

db = SQLDatabase.from_uri(psql_uri, sample_rows_in_table_info=3)
db.get_usable_table_names()

如果你对我们在 SQL 数据库连接中使用的 sample_rows_in_table_info 参数感到好奇,Rajkumar 等人在他们的论文中(arxiv.org/abs/2204.00498)展示了从表中包含几行样本数据可以提高模型在创建模式下查询数据的性能。在 LangChain 中,你可以简单地设置 sample_rows_in_table_info,并确定从每个表中提取的样本行数,这些样本行将被附加到每个表的描述中。

为了测试 SQL 数据库连接,我使用 db.get_usable_table_names() 打印了可用表的列表。它也应该返回以下表的列表给你。

['actor',
 'address',
 'category',
 'city',
 'country',
 'customer',
 'film',
 'film_actor',
 'film_category',
 'inventory',
 'language',
 'payment',
 'rental',
 'staff',
 'store']

下一步是最重要的步骤。借助我们的 LLM 模型和 SQL 数据库连接,我们现在应该能够实例化我们的链。在展示实例化之前,让我们先对链有更多了解。

现在,我们正在使用来自 LangChain 的 SQL 链来获取人类问题,将其转换为 SQL 查询,在数据库上运行它,并检索结果。

# Definining Our SQL Dabatabe Chain

db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)

最后,我们使用 run() 方法将输入/问题传递给链,并获取最终响应。

# Define a Function To Run the Chain with Our Query

def query(input: str) -> str:
    response = db_chain.run(input)
    return response

现在是测试代码的时候了。我们从一个简单的查询开始,该查询只需查询一个表。

# Example 1:

query("What is the average length of films released in 2006")

该链接收我们的自然语言查询,并首先将其转换为 SQL 查询。然后,使用 SQL 数据库连接,它在数据库上运行 SQL 查询。返回的响应为 LLM 提供了上下文,并与原始人类查询一起触发了响应。在这种情况下,你可以看到最终的响应:

> Entering new SQLDatabaseChain chain...
What is the average length of films released in 2006
SQLQuery:SELECT AVG(length) FROM film WHERE release_year = 2006
SQLResult: [(Decimal('115.2720000000000000'),)]
Answer:The average length of films released in 2006 is 115.272 minutes.
> Finished chain.
**'The average length of films released in 2006 is 115.272 minutes.'**

首先,由于 verbose=True(我们在其中定义了 db_chain),我们可以获得更多关于构建的 SQL 查询和返回的 SQL 结果的信息。如果你关闭 verbose,你只能看到最终结果(用粗体标记)。最终答案正确显示了 2006 年上映的电影的平均时长是 115.272 分钟(你可以在 Postgres 上使用你自己的 SQL 查询进行验证)。

第二个问题稍微复杂一些,需要连接三个表。

# Example 2:

query("Which actor played in movies with total longer duration? And how much was the duration?")

这个问题询问的是在电影总时长超过其他任何演员的演员。这个问题需要连接三个表:actor、film_actor 和 film。以下是链响应:

> Entering new SQLDatabaseChain chain...
Which actor played in movies with total longer duration? And how much was the duration?
SQLQuery:SELECT a.first_name, a.last_name, SUM(f.length) AS total_duration
FROM actor a
JOIN film_actor fa ON a.actor_id = fa.actor_id
JOIN film f ON fa.film_id = f.film_id
GROUP BY a.actor_id
ORDER BY total_duration DESC
LIMIT 1;
SQLResult: [('Mary', 'Keitel', 4962)]
Answer:Mary Keitel played in movies with a total duration of 4962 minutes.
> Finished chain.
**'Mary Keitel played in movies with a total duration of 4962 minutes.'**

如你所见,我们超简单的 LangChain 应用成功地理解了这些表之间的关系,并构建了 SQL 查询。

总结

在本文中,我们介绍了一款强大的开源工具,叫做 LangChain,它使我们能够构建基于 LLM 的应用程序。

然后我们使用 SQLDatabaseChain 构建了一个应用程序,该应用程序根据用户的问题查询 SQL 数据库并返回结果。

这个简单的问答应用可以扩展成一个更复杂的业务分析助手,供企业内部的任何人每天使用,从专有数据中获取最新的洞察。

但什么是 LDA?使用类似于 3Blue1Brown 的数学动画来解释。

原文:towardsdatascience.com/but-what-is-lda-explained-using-mathematical-animation-like-3blue1brown-4e8825334d84

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Lan Chu

·发布于Towards Data Science ·13 分钟阅读·2023 年 6 月 5 日

让你的同事们印象深刻 😉

你是否曾经为解释数学概念而苦恼过?3Blue1Brown是我最喜欢的 YouTube 频道,它提供了很酷的数学和统计主题的视频和动画。直到我观看了这个频道上的可视化解释,我才真正理解了二项分布🤷‍♀️

如果你能够了解这些动画是如何制作的,以便你能创建类似的动画来解释数据科学概念,并让你的队友和经理们印象深刻,那岂不是很棒吗?🤩😍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LDA 生成过程。作者制作的 Gif。

好吧,你真幸运,因为你可以使用Manim来实现这一点!😍它是一个免费的开源项目,允许我们使用 Python 创建数学动画,最初由Grant Sanderson编写,现在由 Manim 社区维护。

在这篇文章中,我们将学习如何在 Manim 中创建一些基本元素,并应用我们所学的内容来动画展示如何生成文档,使用的是 Latent Dirichlet Allocation (LDA)。如果你希望理解 LDA 的工作原理,我有一篇文章可以帮助你。在这篇文章中,我们将假定你已经理解了 LDA 的工作原理。好了,让我们开始吧。

什么是 Manim

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Manim 是一个 Python 库,它允许用户创建精确的数学动画,类似于3Blue1Brown的视频。Manim 由以下主要组件构建,并且需要较新的 Python 版本(3.7–3.10)才能运行:

  1. Python

  2. pycairo 用于制作图形

  3. FFmpeg 用于将帧转换为视频

  4. LaTeX 用于编写文本和公式

Manim 构建模块

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Manim 示例

本质上,manim 将三个概念结合起来以生成数学动画: MobjectAnimation, 和 Scene

Mobject 是 Mathematical Object 的缩写。它们是所有 manim 动画的基本构建块。每个从 Mobjects 派生的类代表一个可以在屏幕上动画化和显示的对象,例如形状、方程或图表。

manim 的核心是 Animation,这是在两个 Mobjects 之间进行插值的过程。它定义了可以应用于 Mobjects 的变换和运动,例如 旋转淡出

Scene 类是你动画的画布。每个 Mobject 都必须被 [添加](https://docs.manim.community/en/stable/reference/manim.scene.scene.Scene.html#manim.scene.scene.Scene.add) 到一个场景中才能显示,每个动画也必须通过场景 [播放](https://docs.manim.community/en/stable/reference/manim.scene.scene.Scene.html#manim.scene.scene.Scene.play)

设置环境

你可以通过运行以下命令创建一个新的环境并使用 conda 安装 Manim:

conda create -n my-manim-environment
conda activate my-manim-environment
conda install -c conda-forge manim​

最好通过 conda 安装 manim,因为 conda 会处理所有的依赖项,如 ffmpeg、pycairo 等,你不需要担心安装额外的依赖项。LaTeX 是一个可选的依赖项,不会通过 conda 安装。为了使用 Manim 的 LaTeX 接口,例如渲染公式,你可以通过运行以下命令来为 macOS 安装 LaTeX:

brew install --cask mactex-no-gui​

在 Ubuntu 上,你可以运行

sudo apt install texlive

现在,你应该已经成功安装了 Manim。很好,我们开始吧。

使用 Manim 创建基本元素

在这一部分,我们将学习如何使用 Manim 创建基本的 Mobjects,比如箭头、曲线和条形图。这将为我们在下一节中创建 LDA 生成过程的动画做好准备。

创建基本元素 - 一个箭头

首先,让我们导入 manim 库的所有内容:

from manim import *

在 Manim 中,脚本动画的代码通常写在construct()方法内,该方法属于Scene类。在这个方法内,你可以创建对象,将它们显示在屏幕上,并对其进行动画处理。例如,你可以使用Arrow类创建两个箭头,并使用shift()方法将它们排列在一起,shift()方法用于调整Mobject的位置。最后,我们将使用Create类来初始化对象的动画,并通过调用play()方法将动画添加到场景中:

from manim import *
from manim.mobject.geometry.tips import ArrowSquareTip
class ArrowExample(Scene):
    def construct(self):
        arrow_1 = Arrow(
            start=RIGHT, end=LEFT, color=BLUE
        )  # Specifies the starting point of the arrow as the right side.
        arrow_2 = Arrow(
            start=RIGHT, end=LEFT, color=BLUE, tip_shape=ArrowSquareTip
        ).shift(
            DOWN
        )  # Shifts the position of the arrow downward
        self.play(Create(arrow_1))
        self.play(Create(arrow_2))

将上面的脚本保存到Arrows.py文件中。现在,在你存储这个文件的项目文件夹中,运行以下命令以生成脚本的视频(“ -p”选项允许你在动画渲染后显示视频)

manim -p manim.py Arrows.py

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建基本元素 - 条形图

我们还可以使用 Manim 中的BarChart类来创建条形图。在下面的示例中,我使用以下配置创建了一个条形图:

from manim import *

class BarChartExample(Scene):
    def construct(self):
        # Create the initial bar chart
        barchart1 = BarChart(
            values=[0.1, 0.2, 0.3],
            y_range=[0, 0.6, 0.2],
            bar_names=["food", "animals", "sport"],
            y_length=6,
            x_length=10,
            x_axis_config={"font_size": 36}
        )
        self.play(Create(barchart1))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但仅仅创建条形图并不有趣。让我们看看能否将初始条形图转变为最终的条形图。为此,我们将使用强大的[animate](https://docs.manim.community/en/stable/reference/manim.mobject.mobject.Mobject.html#manim.mobject.mobject.Mobject.animate)方法。

.animate

animate()是所有 Mobjects 的一个属性,允许你展示对象随时间变化的情况,如在动画过程中改变对象的位置、颜色、大小或形状。在下面的示例中,我们将为场景中已经存在的第一个条形图创建动画,并使用animate.become()将其转换为第二个条形图:

from manim import *

class BarChartExample(Scene):
    def construct(self):
        # Create the initial bar chart
        barchart1 = BarChart(
            values=[0.1, 0.2, 0.3],
            y_range=[0, 0.6, 0.2],
            bar_names=["food", "animals", "sport"],
            y_length=6,
            x_length=10,
            x_axis_config={"font_size": 36}
        )

        # Create the second bar chart
        barchart2 = BarChart(
            values=[0.4, 0.3, 0.3],
            bar_names=["food", "animals", "sport"],
            y_length=6,
            x_length=10,
            x_axis_config={"font_size": 36}
        )

        self.play(Create(barchart1)) # draw the first bar chart

        # Animate the first bar chart to become the second one
        self.play(barchart1.animate.become(barchart2), run_time=1.5)
        self.wait(2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建基本元素 - 曲线

在 Manim 中,Axes是一个用于创建坐标系统可视化表示的类,可以在其中添加图形、点、线等数学对象。在这个例子中,我们将使用Axes类来绘制正弦函数。首先,使用一些特定配置创建Axes对象。接下来,我们将使用axes.get_axis_labels()方法为正弦曲线获取名称。标签通过add()方法添加到axes中,最后,VGroup类用于将axessin_curve分组并一起移动。生成的动画将显示正弦函数,如下所示:

from manim import *
class SinFunctionPlot(Scene):
    def construct(self):
        axes = Axes(
            x_range=[-10, 10, 1],  # x-axis range and step size
            y_range=[-1.5, 1.5, 1],  # y-axis range and step size
            x_length=10,
            axis_config={"color": BLUE},
            x_axis_config={
                "numbers_to_include": np.arange(-10, 10, 2),
                "numbers_with_elongated_ticks": np.arange(-10, 10, 2),
            },
        )
        axes_labels = axes.get_axis_labels(Tex("sin(x)"))
        # add labels to the axes object
        axes.add(axes_labels)
        # create the sin function
        sin_curve = axes.plot(lambda x: np.sin(x), color=RED)
        plot = VGroup(axes, sin_curve)
        # Incrementally show the plot
        self.play(Create(plot))
        self.wait(2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Manim 创建 LDA 动画

很棒,到现在你已经学会了如何在 Manim 中创建一些元素,如箭头、曲线和条形图。那我们将所学应用到 LDA 模型生成文档的动画中如何呢?

基本上,LDA 生成过程包含两个组件:主题分布和词汇分布。因此,我们将通过动画展示文档是如何通过 LDA 生成的,具体表现为词汇和主题是如何被选择的。

LDA 使用Dirichlet 和多项式分布。然而,为了能够在二维中可视化数据,我们将考虑一个更简单的示例,其中我们的文档只包含两个主题:食物 🍕 和动物 🐖。这使我们可以使用 Beta 分布而不是 Dirichlet 分布来可视化主题分布。

创建主题分布

Beta 分布的概率密度曲线 (PDF)

我们将从创建 Beta 分布的概率密度曲线开始。如何绘制这条曲线?没错!我们将首先设置一个Axes对象,以便在其上绘制 PDF。我将使用以下一些预定义的配置:

ax = Axes(
    x_range=[0, 1],
    y_range=[0, 3],
    tips=False,
    x_length=config["frame_width"] / 3,
    y_length=config["frame_height"] * 0.6,
).add_coordinates()

在设置好 Axes 对象后,通过调用get_x_axis_label()ax.get_y_axis_label()方法为 x 轴和 y 轴添加标签会很不错。为了书写标签,我们将使用Tex类提供的 LaTeX 语法。经过一些美化处理,标签就准备好了:

 x_label = ax.get_x_axis_label(
      Tex("probability").scale(0.7), edge=DOWN, direction=ORIGIN
  )

  y_label = ax.get_y_axis_label(
      Tex("probability density").scale(0.7).rotate(90 * DEGREES),
      edge=LEFT,
      direction=LEFT,
      buff=0.2,
)
ax.add(x_label, y_label)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很好,我们现在将通过使用类中的参数𝛼和𝛽创建一个 beta 分布对象来创建 PDF 曲线,并将该曲线添加到 Axes 对象中:

alpha = 2
beta = 5
num_samples = 1

def pdf(x):
    return dist.pdf(x)

dist = scipy.stats.beta(self.alpha, self.beta)
pdf_curve = ax.plot(pdf, x_range=[0, 1], color=BLUE_C)
# add the PDF curve to the ax object.
ax.add(pdf_curve)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很棒!每个好的图表都有一个标题,让我们使用Tex类为 PDF 曲线添加一个标题:

title_pdf = (
    Tex("Dirichlet Distribution's PDF")
    .set_color_by_gradient(*bar_kwargs["bar_colors"])
    .set_fill(color=WHITE, opacity=0.3)
    .set_stroke(width=1.2)
    .set(width=7)
    .to_corner(UL)
)

为了显示 PDF 曲线使用了 alpha 和 beta 参数,我想通过创建两个Tex对象并使用.next_to()方法将其显示在轴旁边来将其包含在动画中。以下代码块将完成这项工作:

a_tex = Tex(r"$\alpha = 2$", color=BLUE).scale(0.7)
b_tex = Tex(r"$\beta = 5$", color=BLUE).scale(0.7)
ax.add(a_tex, b_tex)
a_tex.next_to(ax, direction=UP + LEFT, aligned_edge=RIGHT)
b_tex.next_to(a_tex, DOWN)

最后,我们将使用WriteCreate类来在屏幕上写入 alpha、beta 值,并绘制轴和 PDF 曲线:

self.play(Write(a_tex), Write(b_tex))
self.play(Create(ax))
self.play(Create(pdf_curve), run_time=2)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好的。接下来要做的是动画演示 LDA 过程中如何创建主题分布。我们的文档包含 2 个主题:食物 🍕 和动物 🐖。我们将创建一个函数来返回一个BarChart对象,显示每个主题在文档中出现的概率。Beta 分布以 alpha 和 beta 作为参数,额外的样式和自定义选项可以通过kwargs传递:

alpha = 2
beta = 5

def get_barchart(self, alpha, beta, width, height, zeros=True, **kwargs):
    num_samples = 1
    if zeros is True:
        data = [0, 0]
    else:
        dist = scipy.stats.beta(alpha, beta)
        prob_0 = dist.rvs(num_samples)[0]
        prob_1 = 1 - prob_0
        data = [prob_0, prob_1]

    bar_chart = BarChart(values=data, x_length=width, y_length=height, **kwargs)
    return bar_chart

bar_kwargs = {
     "x_length": config["frame_width"] / 2.5,
     "y_length": config["frame_height"] - 3.25,
     "bar_colors": [RED, GREEN, BLUE, YELLOW],
     "y_range" : [0, 0.7, 0.15],
}

接下来,我们将通过初始化 BarChart 创建一个 manim 条形图对象bar,并将条形图添加到屏幕的右下角。接下来,我们希望通过创建显示标签的 Tex 对象来标记每个条形,并使用.next_to()方法将标签放置在相应条形的下方。最后,我们使用Create类绘制并显示条形图的创建过程:

bar = BarChart([0.7, 0.3], **bar_kwargs)​
bar.to_edge(DOWN + RIGHT)​
tex_animals = Tex("animals")
tex_animals.next_to(bar.bars[0], DOWN, buff=0.1)
tex_food = Tex("food")
tex_food.next_to(bar.bars[1], DOWN, buff=0.1)​
self.play(Create(bar))
self.play(Write(tex_food), Write(tex_animals))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了模拟从 Beta 分布中进行多次重采样,我们将创建循环,在每次迭代中生成一个新样本,计算相应的概率,并使用change_bar_values方法相应地更新条形图的值:

# resample 10 times
for i in range(10):
    topic_distribution = scipy.stats.beta(self.alpha, self.beta)
    probability = new_dist.rvs(self.num_samples)[0]
    new_data = [probability, 1 - probability]

    if i == 0:
        dot = Dot(ax.coords_to_point(probability, 0))
        self.play(Create(dot), bar.animate.change_bar_values(new_data))

    else:
        self.play(
            dot.animate.move_to(ax.coords_to_point(probability, 0)),
            bar.animate.change_bar_values(new_data),
        )

    self.wait(1)

将所有内容结合起来,我们就有了以下动画:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你看到一个 PDF 曲线和柱状图被绘制的动画,恭喜你!你刚刚从头开始编写了你的第一个 Manim 场景,用来显示 LDA 主题分布。

创建词汇分布

太好了,我们有了主题分布。然而,一个主题还应该包含属于它的词汇。假设我们的词汇表包括以下十个词:

{🍌,🥝,🍋,🍓,🍅,🐥,🐖,🐑,🐊,🦓}

并且每个文档将仅包含 5 个词。为了可视化 LDA 的生成过程,我们将分别显示每个主题的主题分布和词汇分布,两个单独的柱状图。主题分布将与我们之前做的相同:

topic_distribution = BarChart(
    values=[0,0],
    bar_names=['animals', 'food'],
    y_axis_config={"font_size": 36},
    y_length=3,
    x_length=5,
    y_range=[0, 0.6, 0.1],
)

不幸的是,对于词汇分布,我们不能将表情符号列表传递给 bar_names,这必须一个个手动添加到正确的位置。我们将为此创建一个辅助函数:

words = [
    'banana', 
    'kiwi', 
    'lemon', 
    'strawberry', 
    'tomato', 
    'chicken', 
    'pig', 
    'sheep',
    'crocodile',
    'zebra'
]
def add_svg_xticks(bar_chart):
    """Adds svg symbols instead of standard x-ticks to a BarChart."""
    for i, word in enumerate(words):
        symbol = SVGMobject(f"icons/{word}.svg", width=0.4)
        symbol.next_to(bar_chart.bars[i], DOWN, buff=0.3, aligned_edge=DOWN)
        bar_chart.add(symbol)

在这里,我们使用 symbol = SVGMobject(f”icons/{word}.svg”) 从磁盘加载一个 SVG 符号,并使用 .next_to() 方法将其移动到对应的柱子正下方。BarChart 包含 10 根柱子(因为我们的词汇表中有 10 个词汇),并且第“i”根柱子可以通过 bar_chart.bars[i] 来引用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了说明主题和词汇的随机选择,我们在场景中添加两个箭头:

arrow_topic = Line(ORIGIN, DOWN * 0.8).add_tip().set_color(BLUE)
arrow_word = Line(ORIGIN, DOWN * 0.8).add_tip().set_color(BLUE)

这将绘制一条小的垂直线,.add_tip() 将箭头头部添加到线条上。这些箭头将出现、消失并移动,以说明在随机选择过程中选择了哪个主题和哪个词汇。

我们通过从 Dirichlet 分布中采样来开始动画,以获取每个主题的词汇分布:

topic_p = scipy.stats.dirichlet(self.alphas_topics).rvs(1)[0]
word_p1 = scipy.stats.dirichlet(self.alphas_words_topic1).rvs(1)[0]
word_p2 = scipy.stats.dirichlet(self.alphas_words_topic2).rvs(1)[0]
word_p = np.concatenate((word_p1, word_p2))

​并通过让每根柱子从零变换到其初始值来初始化动画:

self.play(
    topic_distribution.animate.change_bar_values(topic_p),
    word_distribution.animate.change_bar_values(word_p),
)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们从主题分布中随机采样一个主题(这是通过多项分布完成的),并使用箭头可视化选择。这可以通过在选择的第一个主题/词汇时将其淡入场景来实现:

# move
arrow_topic.next_to(topic_distribution[0][topic], UP, buff=0.1)
arrow_word.next_to(word_distribution[0][word], UP, buff=0.1)
# animate
self.play(FadeIn(arrow_topic))
self.play(FadeIn(arrow_word))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

或者通过播放一个运动动画,当选择了新的主题/词汇时:

# animate move
self.play(arrow_topic.animate.next_to(topic_distribution[0][topic], UP, buff=0.1))
self.play(arrow_word.animate.next_to(word_distribution[0][word], UP, buff=0.1))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在选择了主题和词汇,我们可以最终开始编写我们的文档。我们复制所选的词汇,并将该词汇动画化地移动到我们正在生成的文档中:

word_symbol = create_word_token(word)
word_symbol.next_to(
word_distribution[0][word], DOWN, buff=0.3, aligned_edge=DOWN
)
topic_symbol = create_topic_symbol(row, topic)
self.play(FadeIn(topic_symbol))
self.play(word_symbol.animate.move_to(topic_symbol.get_center()))
self.play(FadeOut(topic_symbol))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们重复选择主题和词汇的过程,直到达到我们希望的文档大小,在我们的例子中是 5 个词。要过渡到下一个文档,我们使箭头渐隐:

self.play(FadeOut(arrow_topic, arrow_word))

并创建一个新行以编写新文档:

new_row = VGroup(Tex(f"doc {doc_index}: "))
new_row.next_to(row, DOWN, buff=0.1, aligned_edge=LEFT)
self.add(new_row)
row = new_row

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并重新采样词汇/主题分布:

topic_prob = dirichlet(self.alphas_topics).rvs(1)[0]
word_prob = np.concatenate(
    [
        dirichlet(self.alphas_words_topic1).rvs(1)[0],
        dirichlet(self.alphas_words_topic2).rvs(1)[0],
    ],
)
self.play(
    topic_distribution.animate.change_bar_values(topic_prob),
    word_distribution.animate.change_bar_values(word_prob),
)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并对任意多个文档重复整个过程。在下面的示例中,我们创建了 3 个文档,每个文档包含 5 个词。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总结

恭喜!你刚刚在 Manim 中创建了一个 LDA 生成过程。在这篇文章中,我们学习了:

  1. Manim 的三个主要构建模块:
  • Mobjects:可以在屏幕上显示的数学对象,例如 CircleSquareAxes 等。

  • 定义可以应用于 Mobjects 的转换和移动的动画。

  • 场景:场景是你动画的画布,显示 Mobjects。

2. 创建基本的 Manim 对象,例如箭头、条形图和曲线

3. 动画化生成文档的过程,使用 LDA。

Manim 提供了许多超出本文范围的功能。最好的学习方式是通过实践,因此我鼓励你进一步探索并尝试自己的示例。我也很期待看到你的动画!

参考资料

  1. Manim 文档:Manim Community v0.17.3

  2. 如何使用 Python 创建类似 3Blue1Brown 的数学动画 | 作者 Khuyen Tran | Towards Data Science

代码

产生所有动画的完整代码可以在 这里 找到。

BYOL —对比自监督学习的替代方法

原文:towardsdatascience.com/byol-the-alternative-to-contrastive-self-supervised-learning-5d0a26983d7c

🚀Sascha 的论文俱乐部

Bootstrap Your Own Latent: A New Approach to Self-Supervised Learning 由 J. Grill 等人

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Sascha Kirch

·发表于 Towards Data Science ·10 分钟阅读·2023 年 9 月 7 日

在今天的论文分析中,我们将深入探讨关于 BYOL (Bootstrap Your Own Latent) 的论文。它提供了一个对比自监督学习技术的替代方案,能够去除对大量负样本和庞大批量大小的需求。此外,它在理解今天最先进的基础模型(如 DINO 系列,包括 DINOv2)的道路上具有里程碑式的意义。

尽管对比自监督学习框架仍然有些直观,但 BYOL 起初可能会让人感到困惑和不安。因此,这是一个很好的论文来一起分析。让我们深入了解它,揭示其核心思想吧!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Sascha Kirch 创作,来源于 出版物

论文: Bootstrap your own latent: A new approach to self-supervised Learning 由 Jean-Bastien Grill 等人,2020 年 6 月 13 日

资源: GitHub

类别: 相似性学习、表征学习、计算机视觉、基础模型

其他讲解:

[CLIP] — [GLIP] — [Segment Anything] — [Depth Anything] — [DINO] — [DDPM]

大纲

  1. 背景与概述

  2. 声称的贡献

  3. 方法

  4. 实验

  5. 结论

  6. 进一步阅读与资源

背景与概述

BYOL 属于通过相似性学习进行的自监督表示学习。自监督意味着没有提供明确的真实标签,但可以从未标记的数据中构建监督信号。表示学习意味着模型学习将输入编码到一个维度较低且语义丰富的表示空间中。最后,在相似性学习中,相似的特征在潜在表示空间中被映射得相互接近,而不相似的特征则被映射得更远。这些表示在许多深度学习任务中至关重要,这些任务利用这些表示来生成新数据、执行分类、分割或单目深度估计等。

许多成功的方法,如 CLIP、GLIP、MoCoSimCLR使用了对比学习的方法。在对比学习中,最大化匹配数据对的得分,同时最小化不匹配数据的得分。这一过程严重依赖于训练期间提供的批量大小和负样本数量。这种依赖性使得数据收集和训练变得更加具有挑战性。

BYOL 的目标是:

  1. 摆脱对对比学习所需的负样本和大批量大小的需求。

  2. 减少对特定领域数据增强的依赖,使其适用于其他领域,如语言或图像。

在论文中提到的许多参考文献中,BYOL 突出了它与平均教师动量编码器引导潜在预测 (PBL)的相似性。

声称的贡献(根据作者的说法)

  1. BYOL(Bootstrap your own latent)的介绍,这是一种自监督表示学习方法,不需要负对(如对比学习中的)。

  2. BYOL 表示法被证明优于当时的最新技术水平(论文发布时)。

  3. 与对比学习法相比,BYOL 显示出对批量大小和使用的图像增强方法更具弹性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sascha Kirch

Sascha Kirch 的论文解析

查看列表7 个故事!“DDPM — 去噪扩散概率模型” 论文插图,由 Sascha Kirch 绘制外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方法

既然我们已经了解了 BYOL 声称要解决的问题,让我们尝试理解如何实现这一目标。首先,让我们观察图 1 中呈现的架构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1:框架架构。 图像来源 + Sascha Kirch 的注释。

BYOL 由两个网络组成:在线网络和目标网络。在线网络由三个子模块组成,即编码器、投影器和预测器。目标网络由两个子模块组成,即编码器和投影器。两个网络的编码器和预测器具有完全相同的架构,它们仅在模型权重上有所不同。在线网络在训练过程中进行优化,而目标网络则通过在线网络和自身的指数移动平均来更新其权重。

编码器 —— 编码器由一个 ResNet 卷积神经网络组成。它将输入图像转换为潜在表示。

投影器 —— 通过多层感知器网络(MLP)将潜在空间从 4096 维空间投影到 256 维空间。我猜测投影器对框架的工作并不关键,但 256 只是表示学习领域中常用的方便输出维度。

预测器 —— 旨在从在线网络的投影潜在空间中预测目标网络的投影潜在空间。避免表示崩溃至关重要。

在训练过程中,对输入图像应用两个不同且随机选择的增强来构建该图像的两个不同视图。一个视图被输入到在线模型中,另一个视图被输入到目标模型中。这些增强包括但不限于:调整大小、翻转、裁剪、颜色扭曲、灰度转换、高斯模糊和饱和度。训练目标是最小化两个网络输出之间的平方 L2 距离。训练后,最终只保留在线网络的编码器作为最终模型!

就这样。简单,对吧?😜 好吧,看完论文后我的表情更像这样:😵 虽然将框架的处理过程分解为其关键组件相对直接,但获得直觉确实花费了我不少时间。

在我们尝试理解为什么 BYOL 实际有效之前,让我们首先简化呈现的方程并揭示它们的奥秘。

数学揭秘

在大致了解了 BYOL 的架构及其训练方式后,让我们仔细看看这些方程。我不得不说,论文中呈现的数学部分比实际需要的要复杂得多。在某些情况下,它的展示方式过于复杂,而在其他情况下,它在清晰度上滞后,留下了解释的空间,造成混淆。

我会专注于那些我认为理解发生了什么的方程。我们从精确倒序分析这些方程开始,为什么不呢?😜

首先,让我们谈谈训练期间模型参数的更新。回顾一下,我们有两个模型:在线模型和目标模型。在线模型通过使用 LARS 优化器优化损失函数来更新。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方程 1:在线网络的权重更新。来源 + Sascha Kirch 的注释

上面的方程简单地说:“通过调用优化器函数对当前参数、这些参数相对于损失函数的梯度以及学习率 eta 进行更新,来更新模型的参数 theta”。

另一方面,目标模型不是通过优化来更新,而是通过从在线模型中复制权重,并对复制的更新权重和目标网络的当前权重应用指数移动平均:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方程 2:目标网络的权重更新。来源 + Sascha Kirch 的注释

上面的方程简单地说:“通过计算当前权重 xi 和在线模型的更新权重的指数移动平均来更新模型的参数 xi”。Tau 遵循余弦调度,以减少整个训练过程中在线模型的贡献。

现在让我们看看用于更新在线模型的损失函数。它被定义为两个其他损失函数的和。这些损失函数具有相同的方程,稍后我们将看到,但在网络的两个不同输入上计算。回忆一下图 1.,从图像 x 生成了两个不同的视角(即 v 和 v’),通过应用不同的增强。一个视角输入到在线模型中,另一个输入到目标模型中。在训练期间,计算损失之前执行两个前向传递,其中网络的输入会交换。输入到在线模型的图像会输入到目标模型中,反之亦然。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方程 3:BYOL 的损失函数。 来源 + Sascha Kirch 的注释

个体前向传递的损失是在线模型和目标模型的 L2 归一化输出的平方 L2 距离。让我们分解论文中的相应方程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方程 4:个体损失函数。 来源 + Sascha Kirch 的注释

注:论文中提到这是均方误差,实际上并不正确。L2 距离没有除以其元素数量。我猜他们将其与计算所有批次的均值混淆了。

BYOL 的直觉

现在,我们已经理解了框架和方程的核心信息,让我们尝试获得一些直觉。我会呈现作者的观点,然后我会尝试加入一些我自己的直觉,虽然知道这可能不准确 🤡。

BYOL 如何学习其表示? — 模型被鼓励生成其两个输入的相同潜在表示,这两个输入代表了同一对象/场景的不同视角。无论图像是模糊的、黑白的还是翻转的,猫仍然是猫。事实上,我认为强大的数据增强在这里至关重要。它基本上告诉模型:“看,这些是同一事物的不同变体,所以忽略这些变体,当提取对象/场景的表示时,将它们视为相等!”。

为什么表示没有崩溃? — 回顾之前我们提到,BYOL 属于相似性学习的范畴。网络不会最简单地将所有内容映射到潜在空间的同一点以实现最高相似度吗?实际上,这是相似性学习中的一个主要困难,称为“崩溃解决方案”。对比学习方法通过为每个匹配提供许多负样本来解决这个问题,以将相似特征映射到潜在空间中的彼此接近,同时将不相似的特征映射到更远的位置。BYOL 通过在在线网络和目标网络之间引入不对称性及其预测子模块,并通过基于指数移动平均的更新规则来解决这个问题,以确保在整个训练过程中预测器的近似最优。

[## 获取 Sascha Kirch 发布的新邮件通知 🚀

获取 Sascha Kirch 发布的新邮件通知 🚀 想要了解更多深度学习知识或保持最新动态…

medium.com](https://medium.com/@SaschaKirch/subscribe?source=post_page-----5d0a26983d7c--------------------------------)

实验

BYOL 的作者展示了实验和消融研究,以证明他们方法的有效性。

批量大小的消融研究

从对比表示学习方法(例如,CLIP 和 GLIP)我们知道,在训练过程中,批量大小有很大的依赖性。例如,CLIP 是在批量大小为 32,768 的情况下训练的,这在考虑到它是一个多模态语言-图像模型时显得非常疯狂。

作者声称,由于 BYOL 不需要负样本,它对较低批量大小的敏感度较低,他们通过图 2 所示的实验进行了验证。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2:批量大小的影响。图片来源 + Sascha Kirch的注释。

可惜,这对于我的私人笔记本电脑来说可能仍然太大了 😅

图像增强的鲁棒性消融研究

SimCLR论文表明,对比视觉方法对图像增强的选择非常敏感,特别是那些影响颜色直方图的增强。虽然相同图像的裁剪部分共享类似的颜色直方图,但负样本对的裁剪部分则不然。模型在训练过程中可能会走捷径,专注于颜色直方图的差异,而不是语义特征。

作者们声称,BYOL 对图像增强选择的鲁棒性更强,因为在线和目标网络的更新方式。虽然这一假设得到了实验的支持,但仍然存在较强的依赖性,因此性能有所下降。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3:对图像增强的鲁棒性。图片来源 + Sascha Kirch的注释。

在 ImageNet 上的线性评估

在表示学习领域,一个重要的特征是模型将语义丰富的特征投射到潜在空间的能力,以便对相似特征进行聚类,并将不同的特征分开。一个常见的测试是冻结模型(对于 BYOL,只冻结在线模型的编码器),并在表示的基础上训练线性分类器。

BYOL 的线性评估已在 ImageNet 上进行,并与许多其他模型进行了比较,超越了当时的最新技术。

你会在许多论文中发现 ResNet-50 编码器与其他 ResNet 变体的区别。只是 ResNet-50 已经成为评估性能的标准网络。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1:在 ImageNet 上的线性评估。来源

半监督微调用于分类

表示学习中的另一个典型实验设置是模型在特定下游任务和数据集上进行微调时的表现。

表 2 展示了在分类任务上对 BYOL 进行微调时使用 1%或 10%的整个 ImageNet 训练集的指标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 2:在 ImageNet 上的半监督训练。来源

迁移到其他视觉任务

作者们还展示了他们在语义分割任务和单目深度估计任务(计算机视觉的两个重要领域)中迁移学习 BYOL 的实验。

与之前的方法相比,差异微乎其微,但我想这里的关键信息是,“我们有一种不同的方法,效果同样出色。”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 3:迁移到其他视觉任务。来源

结论

BYOL 提出了一种自监督表示学习的替代方法。通过实现两个进行相似性学习的网络,BYOL 可以在没有对比学习方法所需的负样本的情况下进行训练。为了避免崩溃解,目标网络通过 EMA 从在线网络中更新,并在在线网络之上构建了一个额外的预测子模块。

进一步阅读与资源

如果你已经读到这里:恭喜🎉并感谢😉!既然你似乎对这个话题很感兴趣,这里有一些进一步的资源:

以下是基于 BYOL 的论文列表:

  1. DINO: 自监督视觉变换器中的新兴特性

  2. DINOv2: 无监督学习强健的视觉特征

这里是我关于对比学习方法的两篇文章:CLIP 和 GLIP,用于自监督表示学习:

## CLIP 基础模型

论文总结——从自然语言监督中学习可迁移的视觉模型

towardsdatascience.com ## GLIP: 将语言-图像预训练引入目标检测

论文总结:基础语言-图像预训练

towardsdatascience.com

字节对编码初学者指南

原文:towardsdatascience.com/byte-pair-encoding-for-beginners-708d4472c0c7

一份通俗易懂的 BPE 标记器指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Mina Ghashami

·发布于Towards Data Science ·6 分钟阅读·2023 年 10 月 10 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

在这篇文章中,我们将深入了解一种最著名的标记化算法,即字节对编码(BPE)。它被广泛应用于许多最先进的大型语言模型中,如 BERT 家族、BART 和 GPT 家族。

让我们开始吧。

字节对编码(BPE)

字节对编码(BPE)是一种基于语料库的子词标记化算法。它是基于语料库的,因为它使用训练语料库来学习频繁的字符(或符号)并将其合并成一个符号。它也是一种子词标记器,因为它将文本分解为比(或等于)单词更小的单元。

下面的图像展示了句子“ it is raining”的子词标记化。请注意,虽然“it”和“is”是完整的单词标记;“rain”和“ing”是“raining”的子词。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

BPE 算法有两个主要部分:标记学习器、标记分割器。

1- 标记学习器:它处理一组文本并创建一个包含标记的词汇表。这些语料库作为训练语料库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

标记学习器处理一组文本并建立一个词汇表 —— 图片由作者提供

2- 标记分割器:它将一段文本(如句子)分割成标记。该文本是测试数据。我们利用从前一步中获得的学习,在这一步中对测试数据进行标记化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

标记分割器将句子转换为其标记 —— 图片由作者提供

值得一提的是,

“字节对编码(BPE)(Gage,1994)是一种旧的数据压缩技术,它通过迭代替换序列中最频繁的字节对,用一个未使用的字节。”[1]

我们知道的当前 BPE 算法用于分词,适应了这个算法,但不是合并频繁的字节对,而是合并频繁的字符(或字符序列)。

算法的完整伪代码如下。让我们按照伪代码一步一步地学习这个算法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

BPE 伪代码 — 图像来源 [1]

第一阶段如下图红框中突出显示:我们通过查看我们拥有的文档语料库来创建一个词汇表,按字符拆分它们,并将每个字符及其出现频率添加到词汇表中。

我们看到我们的文档语料库包含* [low, lower, newest, widest],每个的频率不同。我们使用*来表示单词的结束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第一步 — 图像来源 [1] 由作者修改

在第二步中,对于num_merge=10次,我们依次调用三个函数:

  1. get_stats():此函数返回一个字典(称为 pairs),其中包含词汇表中每对字符及其出现频率。

  2. max():此函数获取 get_stats()返回的字符对,并返回出现频率最高的对。

  3. merge_vocab():将字符对视为一个单位,将每个字符对的所有出现替换为一个单独的单位。它返回更新后的词汇表。

这三个函数一起获取语料库中最常见的字符对,将它们合并为一个符号并更新词汇表。我们将此过程重复 num_merges=10 次。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第二步 — 图像来源 [1] 由作者修改

让我们通过上述示例进行演练。我们的语料库如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

语料库示例 — 图像由作者提供

我们通过将所有单词拆分为字符来构建词汇表。在单词末尾添加 _ 以表示单词的结束,然后将其拆分为字符。在伪代码中,他们使用符号表示单词的结束,但在这里我们使用—。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

语料库中的词汇表 — 图像由作者提供

接下来,我们需要计算语料库中每个字符的频率。为了更好地表示字符频率的语料库,我们将其表示如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

语料库表示 — 图像由作者提供

注意“l o w — 5”表示在“low-”这个词的上下文中,l, o, w 每个字符都重复了 5 次。

接下来,我们找出哪个字符对最常相邻? 我们看到“e”和“r”最常相邻,共出现 8 次。因此,我们将它们合并为一个符号“er”,将其添加到词汇表中,并用新符号更新语料库表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并“e”和“r”为“er” — 图像由作者提供

我们重复这个过程:接下来哪两个符号最常紧挨在一起? 我们发现“w”和“er”最常紧挨在一起出现 8 次。因此,我们将它们合并为一个符号“wer”*。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并“w”和“er”为“wer” — 图片来自作者

我们重复这个过程:接下来最常一起出现的两个符号是“wer”和“—”。我们将它们合并为“wer-”并更新语料库:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并“wer”和“—”为“wer-” — 图片来自作者

频率最高的两个符号是“l”和“o”,它们出现了 7 次。我们将它们合并为“lo”并更新词汇表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并“l”和“o”为“lo” — 图片来自作者

到目前为止,我们已经进行了 4 次合并。我们将继续将符号合并,直到达到 10 次合并。之后,我们的词汇表就准备好了,可以使用 BPE 的分词算法对测试数据进行分词。这就是分词算法的工作原理:

BPE 分词器算法: 在测试数据上运行每个从训练数据中学习到的合并。这些已学习的合并是我们之前添加到词汇表中的符号。按我们从训练数据中学到的顺序逐一在测试数据上运行它们。

注意,字符对的频率在这里并不重要,也不需要额外的学习。只需扫描测试数据以查找已学得的词汇条目,并拆分序列。

BPE Tokens 的属性

BPE 分词器的工作方式会导致生成的 tokens 常常是频繁出现的词汇频繁出现的子词。频繁出现的子词通常是像ester这样的词素。

词素是具有意义的最小语言单位。它们提供关于语言的意义和语法的线索。

需要注意的是,词汇表的大小可以通过控制合并操作的数量来配置。较小的词汇表会导致更频繁的子词单元。

总结

总之,字节对编码(BPE)算法在现代自然语言处理(NLP)中发挥了关键作用,通过高效地将文本拆分为子词单元。其 token 学习器建立了一个子词词汇表,而 token 分词器使用这个词汇表进行文本分词。尽管存在一些缺点,BPE 在各种 NLP 任务中已经证明了其高效性,并且仍然是许多当前大型语言模型(如 GPT-3、BERT 和 RoBERTa)的基础组件。

如果你有任何问题或建议,请随时与我联系:

电子邮件:mina.ghashami@gmail.com

LinkedIn: www.linkedin.com/in/minaghashami/

参考文献

  1. 稀有词汇的神经机器翻译与子词单元

  2. 日语和韩语语音搜索

  3. 子词正则化:通过多子词候选项提升神经网络翻译模型

  4. smltar.com/tokenization.html

  5. SentencePiece:一个简单且语言无关的子词分词器和去分词器,用于神经文本处理

GitHub Actions 中的缓存

原文:towardsdatascience.com/caching-in-github-actions-7ff11b6c1874

加速您的 CI/CD 管道

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Oliver S

·发表于Towards Data Science ·7 分钟阅读·2023 年 11 月 21 日

在这篇文章中,我们将探讨如何缓存GitHub Actions。GitHub Actions 是 GitHub 提供的一个平台,允许自动化工作流,通常用于 CI/CD(持续集成/交付)管道——例如,当想要合并新的 PR 时自动运行单元测试。由于这些管道运行频繁,且执行时间可能显著增长,因此考虑节省时间是很有意义的——缓存动作输出就是一种方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Possessed Photography拍摄,发表于Unsplash

在这篇文章中,我们将讨论缓存。我觉得官方文档简洁且未解答一些问题——因此我在这里想多做一些解释。我们首先简要介绍 GitHub Actions 及其缓存的工作原理,然后通过两个示例进行演示:第一个示例遵循创建素数的原始玩具示例,而第二个示例更现实——我们缓存一个完整的 Python 环境。

GitHub Actions 简介

上一篇文章中,我详细介绍了这一主题——因此这里我们仅简要概述此内容,并且我建议参阅链接中的文章获取详细信息。总的来说,GitHub Actions 允许自动化工作流,通常用于 CI/CD 管道,例如运行单元测试、检查风格指南等。在接收到某些触发事件后,运行器(可以由 GitHub 托管或自定义)会接收由不同步骤组成的任务。让我们用上一篇文章中的一个示例进行演示:

name: Sample Workflow

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
jobs:
  sample_job:
    runs-on: ubuntu-20.04
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3
      - name: Set up Python 3.10.0
        uses: actions/setup-python@v3
        with:
          python-version: "3.10.0"
      - name: Echo 1
        run: echo "Echo 1"
      - name: Echo 2
        run: |
          echo "Echo 2a"
          echo "Echo 2b"

在这里,我们定义了一个名为“Sample Workflow”的工作流,并将代码推送和打开新 PR 设置为事件触发器。工作流包括一个在“ubuntu-20.04”上运行的单个作业——这是一个运行所述 Ubuntu 版本的免费 Git 实例。该作业有不同的步骤,包括检出代码库、设置 Python 和输出不同的消息。

为了运行此工作流,我们需要将其放置到.github/workflows文件夹中。一旦放置并推送到 Github,这个工作流将会在定义的事件触发器上自动运行——我们可以方便地查看定义工作流的状态和输出,例如,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

缓存操作

在奠定基础之后,让我们继续讨论缓存。通过缓存操作,我们可以定义一个缓存步骤。借用我们即将到来的玩具示例,这可以如下所示:

- name: Cache Primes
id: cache-primes
uses: actions/cache@v3
with:
    path: prime-numbers
    key: ${{runner.os}}-primes

缓存由一个键和一个路径唯一标识:如果这两者都存在/填写,缓存将被加载——否则生成。当工作流第一次运行(或某些依赖项发生更改)并生成缓存时,指定在path下的文件夹内容将上传到某个 Github 存储区。这样,缓存就与之前运行的运行器无关,并且始终可用(特别是,你不需要自己的运行器来持久化缓存——可以使用公开的 Github 运行器)。

现在,在接下来的步骤中,我们可以检查缓存是否可用(缓存命中),并跳过它(通常是生成缓存内容的步骤):

- name: Generate Prime Numbers
  if: steps.cache-primes.outputs.cache-hit != 'true'
  run: ./generate_primes.sh

缓存生成素数

话虽如此,让我们给出第一个完整的示例:通过 Github Actions,我们生成前N个素数,并缓存此输出。请注意,这一做法受到原始文档的启发,尽管在我看来更为完整。

这个示例由两个 bash 脚本组成。通过第一个脚本generate_primes.sh,我们生成前N个素数并将它们写入prime-numbers/generate_primes.sh

#!/bin/bash

N=10  # Number of prime numbers to generate
file_path="prime-numbers/primes.txt" # Path where to store the primes

# Remove existing file if it exists
rm -f "$file_path"

# Function to check if a number is prime
is_prime() {
    num=$1
    for ((i=2; i*i<=num; i++)); do
        if ((num % i == 0)); then
            return 1
        fi
    done
    return 0
}

# Create directory for prime numbers if it doesn't exist
mkdir -p "$(dirname "$file_path")"

echo "Generating prime numbers ..."

count=0
number=2
while [ $count -lt $N ]; do
    if is_prime $number; then
        echo $number >> prime-numbers/primes.txt
        ((count++))
    fi
    ((number++))
done

另一个脚本primes.sh读取此文件,并简单地打印存储的素数:

#!/bin/bash

# Read and print prime numbers from the file
if [ -f prime-numbers/primes.txt ]; then
    echo "Prime numbers:"
    cat prime-numbers/primes.txt
else
    echo "File prime-numbers/primes.txt not found."
fi

假设我们想找很多素数,并且这需要一段时间,这与缓存这个过程密切相关,这正是我们用prime_workflow.yml做的:

name: Caching Primes

on: push

jobs:
  build:
    runs-on: ubuntu-20.04

    steps:
    - uses: actions/checkout@v3

    - name: Cache Primes
      id: cache-primes
      uses: actions/cache@v3
      with:
        path: prime-numbers
        key: ${{ runner.os }}-primes

    - name: Generate Prime Numbers
      if: steps.cache-primes.outputs.cache-hit != 'true'
      run: ./generate_primes.sh

    - name: Use Prime Numbers
      run: ./primes.sh

我们检出代码库,在第 2 步调用缓存操作:键由运行器操作系统和后缀“-primes”组成,缓存路径是第一个脚本将结果文件转储到的文件夹。

然后,我们要求工作流生成素数(即运行generate_primes.sh)——如果没有缓存命中,例如,当第一次执行此脚本时。

最后,我们在脚本primes.sh中使用生成的或缓存的素数。查看此工作流的第二次运行,我们观察到确实跳过了“生成”步骤:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

你还可以在Github上找到完整的示例。

缓存 Poetry 环境

现在,让我们来看一个稍微现实一点的示例:强烈建议任何 Python 项目都捆绑一个环境,以确保所有开发者使用相同的包和版本。在 Github Actions 运行器上,仓库通常是全新检出的,这意味着每次都必须重新安装设置的环境。因此,我们在这里展示如何缓存这个环境——即与其下载和安装包,不如将完整的环境缓存并从缓存中下载。特别是,此示例将展示如何使用poetry,这是我管理环境时更倾向使用的工具。

该项目中的示例文件main.py如下所示:

import matplotlib.pyplot as plt
import numpy as np

def plot():
    x = np.linspace(0, 10, 50)
    y = np.sin(x)
    plt.plot(x, y)
    plt.savefig("plot.png")

if __name__ == "__main__":
    plot()

即,我们使用matplotlib绘制简单的正弦曲线,因此需要这个和 numpy。

因此,我们的pyproject.toml文件包含以下内容(这里,我假设你对 poetry 有基本了解——否则可以参考链接的帖子):

[tool.poetry]
name = "myproject"
version = "0.1.0"
description = "…"
authors = ["hermanmichaels <hrmnmichaels@gmail.com>"]

[tool.poetry.dependencies]
python = "3.10"
matplotlib = "3.5.1"
mypy = "0.910"
numpy = "1.22.3"
black = "22.3.0"

正如我们所见,我们安装了所需的包——以及一些每个 Python 项目都不应错过的有用工具

然后,设置环境(包括缓存)的相应 Github Actions 工作流如下所示:

name: Caching Env

on: push

jobs:
  build:
    runs-on: ubuntu-20.04

    steps:
    - uses: actions/checkout@v3

    - name: Set up Python 3.10.0
      uses: actions/setup-python@v3
      with:
        python-version: "3.10.0"

    - name: Install poetry
      run: curl -sSL https://install.python-poetry.org | python3 -

    - name: Cache Env
      id: cache-env
      uses: actions/cache@v3
      with:
        path: ~/.cache/pypoetry
        key: ${{ runner.os }}-env

    - name: Install poetry dependencies
      if: steps.cache-env.outputs.cache-hit != 'true'
      run: poetry install

我们首先安装 Python 和 poetry。在最后一步,我们运行poetry install,它将所有所需的包安装到 poetry 环境中。

本帖的关键点是倒数第二步:在此步骤中,我们定义了一个目标路径为~/.cache/pypoetry的缓存——这是 poetry 环境默认存储的地方。因此,如果再次运行此工作流,并且此键/文件夹组合存在于缓存中,我们将跳过 poetry 安装——而是从云缓存中下载完整的环境。

此示例也可以在相同的演示仓库中找到。

注意:这其中存在权衡。在没有缓存的版本中,我们下载所有包并安装它们。在使用缓存的版本中,我们不需要安装任何东西,而是需要从缓存中下载所有已安装的包。哪个更快应取决于各种因素,如带宽、包的大小和安装时长。如果你有实际的数据点,或者你更喜欢如何处理,请在评论中告诉我!

缓存管理

最后,关于监控和管理缓存的一点说明:当你在 Github 上打开你的仓库,并导航到“Actions / Caches”时,我们会看到如下图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像

这个仓库中使用的所有缓存都被展示出来,例如,指明了它们的大小,我们可以在需要时将其移除。

结论

这结束了我们对 Github Actions 缓存的介绍。这是一个非常有用的功能,因为 CI/CD 流水线通常让开发者等待不耐烦——通过缓存,我们可以减少这些流程的运行时间,并减少对整个系统的负载。

在对主题进行一般介绍后,我们通过两个具体示例展示了如何应用缓存:我们从缓存生成的素数的玩具示例开始,然后展示了如何缓存一个诗歌环境。这个Github 仓库包含了所有示例代码。

感谢阅读!

召唤所有函数

原文:towardsdatascience.com/calling-all-functions-a421434ae0a4?source=collection_archive---------7-----------------------#2023-12-07

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者使用 Dall-E 创建

基准测试 OpenAI 的函数调用与解释

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Amber Roberts

·

关注 发表在 Towards Data Science ·9 分钟阅读·2023 年 12 月 7 日

感谢 Roger Yang 对这篇文章的贡献

对第三方大型语言模型(LLMs)的可观察性主要通过基准测试和评估来实现,因为像 Anthropic 的 Claude、OpenAI 的 GPT 模型和 Google 的 PaLM 2 这样的模型是专有的。在这篇博客文章中,我们将 OpenAI 的 GPT 模型的函数调用和解释与各种性能指标进行基准测试。我们特别关注 GPT 模型和 OpenAI 功能在正确分类幻觉和相关响应方面的表现。下面的结果展示了不同 LLM 应用系统在速度和性能之间的权衡,以及如何利用这些带有解释的结果进行数据标注、LLM 辅助评估和质量检查。我们使用的实验框架也在下面提供,以便从业者可以在默认分类模板上进行迭代和改进。

OpenAI 函数调用和解释

使用 OpenAI 函数调用,你可以描述函数给各种 GPT 模型,这些函数可以用来输出包含调用这些函数的参数的 JSON 对象。函数调用本质上作为一种工具或代理,用于以给定格式记录响应,以可靠地将 OpenAI GPT 模型的能力与外部工具和 API 连接。关于解释,由于许多情况下很难理解 LLM 为何以特定方式响应,这些解释旨在促使 LLM 解释输出是否正确。然后,你可以附上一个输出标签(‘相关’或‘无关’)和 LLM 的解释。下面是一个带有解释的‘相关’评估示例,用于调试 LLM 响应。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

在下面的“结果与权衡”部分,提供了两个用例的比较表格:预测相关性和预测幻觉(分别为表 1 和表 2)。每个表格比较了 GPT-4-turbo、GPT-4、GPT-3.5 和 GPT-3.5-turbo 在特定提示指令和 LLM 属性下的各种分类指标(准确性、精确度、召回率和F1 分数)的表现。

测试的四个基础模型在这些情况下使用上述指标(除了中位处理时间)进行评估。

  • 无 _function_calling & 无 _explanations

  • 有 _function_calling & 无 _explanations

  • 有 _function_calling & 有 _explanations

  • 无 _function_calling & 有 _explanations

因此,LLM 中的提示模板保持不变(即普通的提示完成),例如without_function_calling & without_explanations。具有功能调用但无解释的样本要求 LLM 将其答案放在仅接受枚举作为输入的 JSON 对象中,而具有功能调用和解释的样本要求 LLM 在同一个 JSON 对象中提供解释(详见Google colab notebook)。

基准数据集和评估指标

正确识别 LLM 输出中的幻觉和相关响应是我们客户当前实施 LLM 应用中最大的两个痛点。优化 LLM 评估系统对于幻觉意味着正确识别所有虚构响应,同时跟踪事实输出。对于利用搜索和推荐作为其用户体验的一部分的用例,与用户满意度相关的最重要因素是结果的速度和相关性。为了评估 LLM 系统在相关和无关输出上的性能,您应该了解关键指标:

  • 精确度和召回率:检索到的信息有多相关?

  • 准确性:回应在语境上的准确度有多高?

  • 延迟:系统提供响应需要多长时间?

  • 用户反馈:结果的相关性和响应时间如何影响用户体验?

结果与权衡

这里是关于基准测试 LLM 系统在无关和相关预测上的结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1 作者提供

这里是基准测试 LLM 系统在幻觉和事实预测上的结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 2 作者提供

在分析结果之前,你可以在这个Google colab notebook中自行复现这些结果。请注意,通常情况下,由于 LLM 的非确定性特性,你无法完全复现这些表中的数字,但对于这个 notebook,我们已经添加了一个种子以保证每次采样结果都相同。此外,我们还添加了分层采样,使得二进制类别确实是完全 50/50。请注意,运行此 notebook 需要消耗计算资源与您的 OpenAI API 密钥相关。 默认采样数量设置为 2,但如果您希望复制这篇博文中的结果,可以将数字更改为 100。

中等处理时间

为了清晰起见,这些比较(使用了 100 个样本)是在 Google Colab 上使用标准 OpenAI API 帐户和密钥进行的。因此,虽然在不同的设置下运行时延迟值不太可能完全准确,但最慢和最快的模型将会被重现。

此外,在评估中使用解释可能需要花费 3 到 20 倍的时间来编译(这与函数调用无关)。

关于整体相关性的模型预测能力

  • 延迟:GPT-3.5-instruct > GPT-3.5-turbo > GPT-4-turbo > GPT-4

关于模型预测能力对幻觉的表现

  • 延迟:GPT-3.5-instruct > GPT-3.5-turbo ~ GPT-4-turbo > GPT-4

带有函数调用的 GPT 模型的延迟通常略高于不带函数调用的 LLM,但请注意一些警告。首先,延迟是从 OpenAI 返回的 HTTP 头信息中提取的,因此根据你的帐户和请求方式,延迟值可能会有所变化,因为这些值是由 OpenAI 内部计算的。函数调用的权衡也取决于你的用例。例如,若没有函数调用,你需要通过提供示例和详细描述来精确指定输出的结构。然而,如果你的用例是 结构化数据提取,那么直接使用 OpenAI 函数调用 API 是最简单的。

总的来说,带有函数调用的 LLM 的表现与不使用函数调用而使用普通提示完成的 LLM 相当。你是否决定使用 OpenAI 函数调用 API 而不是提示工程,应该取决于你的用例和输出的复杂性。

GPT 模型性能比较

关于整体相关性的模型预测能力:

  • 性能:GPT-4 ~ GPT-4-turbo ~ GPT-3.5-turbo >>> GPT-3.5-instruct

关于模型预测能力对幻觉的表现:

  • 性能:GPT-4 ~ GPT-4-turbo > GPT-3.5-turbo > GPT-3.5-instruct

有趣的是,在这两种用例中,使用解释并不总是能提高性能。更多内容见下文。

评估指标

如果你在决定使用哪个 LLM 来预测相关性,你可以选择 GPT-4、GPT-4-turbo 或 GPT-3.5-turbo。

GPT-4-turbo 能够准确识别输出的相关性,但在召回所有 50 个示例上有所牺牲,实际上,即使使用解释,其召回率也不比抛硬币好。

GPT-3.5-turbo 也面临相同的权衡,尽管它的延迟较低且准确性较低。从这些结果来看,GPT-4 拥有最高的 F1 分数(精确率和召回率的调和平均值)和总体最佳表现,同时运行时间与 GPT4-turbo 相当。

GPT-3.5-instruct 预测所有内容都是相关的,因此不是一个可行的预测相关性的 LLM。有趣的是,当使用解释时,预测性能显著提高,尽管它仍然低于其他 LLM。同时,GPT-3.5-instruct 无法使用 OpenAI 函数调用 API,并且可能会在 2024 年初被弃用

如果你正在决定选择哪个 LLM 来预测虚假信息,你可以使用 GPT-4、GPT-4-turbo 或 GPT-3.5-turbo。

结果显示,在精确度、准确性、召回率和 F1 分数方面,GPT-4 在识别虚假和事实输出的正确率上比 GPT-4-turbo 高出约 3%。

尽管 GPT-4 和 GPT-4-turbo 的表现略高于 GPT-3.5-turbo(请注意,得出小差距不代表噪声的结论时应使用更多样本),如果你计划使用解释,可能值得使用 GPT-3.5-turbo。

用于预测虚假和事实的解释在 GPT-3.5-turbo 上的返回速度比 GPT-4 和 GPT-4-turbo 快三倍以上,然而,当比较 GPT-4 模型预测虚假信息的召回率时,两个 GPT-3.5 模型的召回率有所下降。

讨论与影响

在决定使用哪个 LLM 进行应用时,需要进行一系列实验和迭代。同样,在决定是否将 LLM 用作评估器时,也需要进行基准测试和实验。基本上,这两种方法是基准 LLM 的主要方法:LLM 模型评估(评估基础模型)和通过可观察性进行 LLM 系统评估。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供 | 在单一基础模型上评估两种不同的提示模板。我们正在测试相同的数据集,并观察它们的精确度和召回率等指标如何对比。

最终,当决定一个 LLM 是否适合你的用例作为性能评估器时,你需要考虑系统的延迟以及相关预测指标的性能。在本文中,我们总结了这些模型的开箱即用表现——没有增加提高速度和性能的技术。请记住,开箱即用时,这些 LLM 都使用零样本模板,因此没有将示例添加到 LLM 提示模板中以改善模型输出。由于这些数据作为基准,团队可以通过提示工程、提示模板(和存储库)、代理、微调以及像 RAG 和 HyDE 这样的搜索和检索应用来提高 LLM 系统性能。

潜在的未来工作:数据标注的解释

通过这种基准测试,我们发现了一些有趣的示例,其中提供解释会改变预测标签。以下示例在没有使用解释时预测为“relevant”,即使真实标签也是“relevant”。由于即使是“黄金数据集”也可能存在标注错误(尤其是在更主观的任务中),LLM 提供的充分解释可能足以编辑真实标签。这可以视为 LLM 辅助的评估或质量检查。

以下是来自维基数据集的一个示例,用于相关性说明。请注意,‘D’列是数据集提供的真实标签,‘E’列是没有调用函数和解释的预测标签,而‘F’列是创建的预测标签(未调用函数),并带有‘G’列中的解释。因此,‘E’列和‘F’与‘G’列是两个独立 LLM 调用的响应。F&G 是从同一次调用中生成的,如下图 1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1(作者提供):脚本截图(代码见 colab)。在这里,标签和解释一起返回,但我们要求首先提供解释(见提示)。

下表展示了当我们拥有真实标签为‘relevant’,LLM 预测标签在没有调用函数的情况下为‘relevant’,但当 LLM 被要求首先提供解释时,标签变为‘irrelevant’的情况。与我们遇到的几个类似示例一样,LLM 对将检索到的答案标记为‘irrelevant’提出了有效的论据。虽然我们许多人经常考虑罗马帝国,但我们可以同意,对于“罗马帝国持续了多久?”的多段回答既不简洁也不够相关,不足以引起最终用户的积极反馈。LLM 辅助的评估有很多可能性,包括为需要数据标记的公司节省成本和时间。这以及解释所提供的可见性,以及 LLM 返回其参考文献(用于预测的文档),都是 LLM 可观测性领域的重大进展。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者示例

结论

希望这篇文章能为那些希望更好地理解并平衡新 LLM 应用系统的性能与速度权衡的团队提供一个良好的开端。正如往常一样,生成式 AI 和 LLMOps 领域正在迅速发展,因此观察这些发现和领域如何随时间变化将是很有趣的。

有问题吗?请在此处或在LinkedInXSlack与我联系!

如何使用 Llama2 和 LangChain 构建本地聊天机器人

原文:towardsdatascience.com/can-a-llama-2-powered-chatbot-be-trained-on-a-cpu-ce9ec6ebe3c2

使用 Python 的概述和实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Aashish Nair

·发表于 Towards Data Science ·6 分钟阅读·2023 年 10 月 12 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Adi GoldsteinUnsplash

目录

∘ 介绍

∘ 案例研究

∘ 第 1 步 — 创建向量存储

∘ 第 2 步—创建 QA 链

∘ 第 3 步 — 创建用户界面

∘ 评估聊天机器人

∘ 结果

∘ 最终判决

∘ 参考文献

介绍

本地模型的出现受到希望建立自己定制 LLM 应用程序的企业的欢迎。这些模型使开发者能够构建可以离线运行并符合隐私和安全要求的解决方案。

这些大规模语言模型(LLMs)最初非常庞大,主要服务于那些拥有资金和资源来配置 GPU 和在大量数据上训练模型的企业。

然而,本地 LLM 现在有了更小的尺寸,这引发了一个问题:普通 CPU 用户是否可以利用这些相同的工具和技术?

这个问题值得考虑,因为用户可以从构建自己的个人本地聊天机器人中获得很多好处,这些机器人可以离线执行任务。

在这里,我们通过在 CPU 上使用 Meta 的 Llama2 构建一个封闭源代码的聊天机器人来探讨这种可能性,并评估其作为个人可靠工具的表现。

案例研究

为了测试在个人电脑上离线运行本地聊天机器人的可行性,让我们进行一个案例研究。

目标是使用量化版本的 Meta 的 Llama2(7B 参数)构建一个聊天机器人。该模型将用于构建一个 LangChain 应用程序,促进响应生成,并可以通过用户界面访问,让人们与应用程序进行互动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聊天机器人图示(由作者创建)

该聊天机器人将使用两个 PDF 文档进行训练(两个文档均可通过 arXiv API 访问):

  1. 计算机视觉在体育中的全面综述:开放问题、未来趋势和研究方向

  2. 深度学习在体育应用中的调研:感知、理解和决策

为了提供背景,这个机器人将在具有以下规格的计算机上进行训练:

  • 操作系统:Windows 10

  • 处理器:Intel i7

  • RAM: 8GB

注:跟随本案例研究需要具备 LangChain 框架和 Streamlit 库的基础知识

第 1 步 — 创建向量存储

首先,我们创建向量存储,它将存储来自文档的嵌入数据,并促进与用户查询相关文档的检索。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建向量存储(由作者创建)

为此,数据必须转换为文本块。这通过使用 PyPDFLoader 加载 PDF 文档,并将文本分割成 500 个字符的块来完成。

接下来,使用来自 HuggingFace 的句子变换器将文本块转换为嵌入。参数中指定设备为“cpu”是很重要的。

在创建了文本块并加载了嵌入模型后,我们可以创建向量存储。对于这个案例研究,我们使用 Facebook AI 相似性搜索(FAISS)。

这个向量存储将被保存在本地,以备将来使用。

第 2 步—创建 QA 链

接下来,我们需要加载检索 QA 链,它从向量存储中检索相关文档,并使用它们来回答用户的查询。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

QA 链(由作者创建)

QA 链需要三个组件:量化的 Llama 2 模型、FAISS 向量存储和一个提示模板。

首先,我们下载量化的 Llama2 模型,该模型可在HuggingFace 仓库中找到。对于这个案例研究,模型通过名为“llama-2-7b-chat.ggmlv3.q2_K.bin”的文件进行下载,占用内存 2.87 GB。

然后使用 CTransformers 加载模型,这是一个用于绑定在 C 中实现的变换器模型的 Python 库。由于我们想要一个生成响应的目标型聊天机器人,因此将temperature设置为 0。

接下来,我们加载先前创建的向量存储。

之后,我们定义提示模板。此步骤是可选的,但由于我们希望与研究论文进行互动,我们需要优先考虑准确性,这可以通过提示中的指令来实现。幻想回答是非常不受欢迎的,因此主要指令是对无法通过提供的 PDF 文档回答的问题回应“我不知道”。

有了这些元素,我们可以创建 QA 链,该链将使用加载的量化 Llama2 模型、向量存储和提示模板生成对用户查询的响应。

最后,我们创建执行响应生成的函数。

第 3 步——创建用户界面

LangChain 应用所需的核心元素已经构建完成,因此我们可以转向为聊天机器人构建用户界面。

Streamlit 库适合这个任务,因为它包含了针对聊天机器人应用的特性。

以下代码将先前构建的函数整合到用户界面中(要查看完整的源代码,请访问 GitHub 仓库)。

Streamlit 应用使用如下:

streamlit run app.py

完成了!我们的个人闭源聊天机器人已成功运行!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聊天机器人用户界面(由作者创建)

评估聊天机器人

我们有了聊天机器人,让我们用 3 个不同的问题来评估其表现:

  1. 计算机视觉在运动分析中的好处是什么?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聊天机器人响应(由作者创建)

2. 给我一个包含计算机视觉的运动项目列表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聊天机器人响应(由作者创建)

3. 用什么算法来追踪运动员?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聊天机器人响应(由作者创建)

结果

总的来说,机器人似乎能够返回令人满意的响应,而不包含未经请求的信息。

然而,从对“用什么算法来追踪运动员?”这个问题的回答中,可以明显看出一个限制,即答案在句子中途被截断。这可以归因于量化版 Llama2 模型的有限上下文窗口(即令牌数量)。聊天机器人无法正确回答需要大量令牌的问题。

此外,一个在响应中未传达的限制是时间。虽然机器人对问题的回答适当,但在这台 CPU 上生成响应平均需要超过一分钟。由于运行时间如此长,使用此工具作为替代手动搜索文档集合中的内容的理由并不充分。

最后,这整个过程消耗了我计算机大量内存,使其他应用程序无法使用。

最终裁决

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Arek Socha提供,来自Pixabay

既然案例研究已经结束,让我们重新审视最初的问题:我们能否在 CPU 上构建 LLM 驱动的应用程序?

答案是:是的……但我们可能不应该。

本案例研究的积极之处在于量化后的 Llama2 模型容易下载并融入应用中,并且聊天机器人能够生成高质量的回应。

然而,有限的令牌、较长的运行时间和高内存使用的组合使得在 CPU 上训练闭源聊天机器人的前景变得不可行。

当然,这一结论是基于进行案例研究所用设备的限制,因此,具有更高处理能力和存储空间的计算机可能会产生更有希望的结果。此外,未来会有更小的 LLM 与更大的上下文窗口公开,使得闭源聊天机器人在 CPU 上构建和使用变得更加容易。

如果你有兴趣了解这个应用在你的设备上表现如何,随时可以查看以下代码库中的代码:

anair123/Llama2-Powered-QA-Chatbot-For-Research-Papers (github.com)

感谢阅读!

参考文献

  1. Naika, B. T., Hashmi, M. F., & Bokde, N. D. (n.d.). 《计算机视觉在体育中的综合评述:开放问题、未来趋势和研究方向》。Arxiv. arxiv.org/pdf/2203.02281

  2. Zhao, Z., Chai, W., Hao, S., Hu, W., Wang, G., Cao, S., Song, M., Hwang, J.-N., & Wang, G. (n.d.). 《深度学习在体育应用中的调查:感知、理解与决策》。Arxiv. arxiv.org/pdf/2307.03353.pdf

人工智能能克服人类的确认偏差吗?

原文:towardsdatascience.com/can-ai-overcome-humans-confirmation-bias-57bee0bc5c8c

人工智能如何补充人类智慧的不足,并作为人类认知偏差的对冲力量

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Stephanie Shen

·发表于 Towards Data Science ·阅读时间 9 分钟·2023 年 11 月 11 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:由 geralt 拍摄,来自 Pixabay

从诺贝尔奖得主丹尼尔·卡尼曼的《思考,快与慢》一书中,我们知道人类的大脑在其应有的功能上远非完美。除了情绪冲动、顽固的成瘾以及自人类文明诞生以来的道德挣扎外,卡尼曼在他的书中全面描述了我们认知偏差的细微差别。更令人沮丧的是,许多偏差渗透到我们生活的方方面面、组织和社会中。鉴于此,我们现在面临两个关键问题。首先,我们如何识别我们决策中的这种偏差的现实?其次,我们如何在决策过程中弥补或防止这些偏差?在本文中,我将从数据科学的角度出发,通过关注最普遍的偏差之一——确认偏差,来回答这两个问题。随着机器学习和人工智能的进步,在它们的帮助下,我们现在看到了识别、克服和防止这些偏差的曙光。

什么是确认偏差?

确认偏差是指解释和寻找信息以确认或支持现有信念或先前结论的倾向。由于确认偏差,人们倾向于通过片面地测试想法、关注支持/积极证据而忽视可能反驳自己观点的替代/矛盾事实来确认自己的信念或假设。确认偏差是无意的,与故意欺骗相对。这种偏差在许多领域的人类生活和社会中具有广泛的影响,包括科学研究、医学、政治、执法、社会心理学和组织决策。

英国心理学家彼得·凯瑟特·瓦森在 1960 年代首次系统性地提出并研究了确认偏差。在他的实验中,瓦森给参与者一个 4 卡片谜题,也称为 Wason 选择任务。这个谜题可以有任何变体,但结果高度可重复。让我们来看一个例子:

桌子上放着四张卡片,每张卡片的一面有一个数字,另一面有一个颜色。规则是如果一张卡片的一个面显示偶数,则另一面应该是蓝色。现在,桌子上你看到四张卡片:3、8、蓝色和红色。你必须翻转哪张卡片来测试规则是否成立?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Wason 选择任务的一个例子:必须翻转哪个卡片来测试规则“如果一张卡片的一个面显示偶数,则另一面是蓝色”? 图片来源:维基百科

每个人都知道需要翻转 8 号卡;有些人可能选择 8 号和蓝色卡。正确的答案是翻转 8 号卡和红色卡,而大多数人会遗漏翻转红色卡。如果你翻转 3 号卡,无论另一面是蓝色还是非蓝色都与规则无关。同样地,如果你翻转蓝色卡发现另一面是奇数,这也不重要,因为规则规定另一面可能是偶数。另一方面,如果你翻转红色卡发现另一面是偶数,那么你就证明了规则被违反。

令人惊讶的是,参与者在各种形式的测试中表现一直很差。人们关注规则的积极支持(另一面是蓝色),但忽视了可能会使规则无效的信息(另一面不是蓝色)。

Wason 选择任务的规则都很简单,具备逻辑条件和结果:如果 P,则 Q。要完全验证规则是否有效,需要确认下面列出的两个标准:

  1. 如果 P,则 Q

  2. 如果不是 Q,则不是 P

平均而言,只有 10%的 Wason 选择任务参与者完全正确地选择了第二种选项,这显示了人类大脑自动关注积极证据来确认结论,但很难检查可能反驳规则的证据。

有趣的是,如果我们在难题中加入社会背景,大多数人能够很快回答正确,主要涉及权限或职责。一个流行的例子是这样的:规则是如果你未满 21 岁,你不能喝酒。假设有四张卡片——啤酒、28、可乐、15。你必须翻转哪张卡片以测试规则是否正确?大多数人会凭直觉快速给出正确答案:翻转啤酒卡以查看另一面是否标注年龄超过 21 岁,并翻转 15 卡以确认另一面是否列出了含酒精的饮料。

什么导致确认偏差?

Wason 选择任务的结果意味着什么?科学家们仍在研究哪些神经回路和机制可以解释确认偏差。但我们可以推导出两点:

  1. 人脑不是通过符号和标记来解决这种逻辑问题的逻辑运算器。

  2. 当人们有社会情境中的规则的先前经验时,偏差可以通过社会背景克服。

参考生物大脑和人工学习中的神经网络学习机制(见文章 “从生物学习到人工神经网络:接下来是什么?”),确认偏差可能是神经网络在模式识别中工作的副产品。对于现有的信念或规则,神经网络通过加强输入前提条件的相关神经连接来进行学习。类似的证据会激活相同的网络,得出相同的结论,同时加强神经连接。相反,要验证对立面,网络需要通过不同的输入数据(非 P)进行单独训练,以得出不同的结论(非 Q)。换句话说,网络可能涉及不同的神经连接来进行独立学习。由于建立另一个神经输出以理解对立效果的障碍和努力,人脑倾向于现有的脑电路。

当人们遵守社会规则时,他们知道如果不遵守会受到惩罚或付出一定的代价。这种对立场景被认为是被纳入大脑的电路中,这解释了为什么在解决社会背景中的难题时,人类没有困难看到另一面。换句话说,大脑首先通过实证数据学习了双方的场景。

然而,还有另一种方法可以防止确认偏差,那就是使用超越我们本能大脑能力的工具。这些通常被称为心理工具。对于 Wason 选择任务,这个工具就是简单的逻辑:

  1. 如果 P,那么 Q

  2. 如果不是 Q,那么不是 P

假设我们将每个规则的前提(P)和结果(Q)插入上述两个场景;无论是否与社会背景相关,我们将 100%正确地解开难题。换句话说,使用正负逻辑这样简单的思维工具可以帮助我们清晰地思考,而不会凭直觉忽视对立面。

然而,在现实世界中,实验室之外的规则更复杂和隐含。数据科学和 AI 可以通过利用相同的原则和策略来帮助人类克服确认偏差。

数据科学和 AI 如何克服确认偏差?

鉴于生物神经网络和人工神经网络之间的学习相似性,我们不希望 AI 一开始就重复人类的偏见。虽然人类克服确认偏差很困难,但 AI 和机器学习有以下优势来克服这些偏差:

  1. 模型和算法以预设的方式解释训练数据。因此,它们不会像人类那样有解释或偏好某些问题而忽略相反的事实。

  2. 数据科学家和工程师在 AI 方面的协作工作使其更加客观,与每个人观点中的人类偏见形成对比。

  3. 对于 AI 来说,增加额外的统计和逻辑工具与流程以防止偏差的发生是很灵活的。

另一方面,由于 AI 和机器学习依赖于人为策划的训练数据,因此需要额外的预防措施以防止将偏差引入模型。因此,我们应关注三个领域来克服确认偏差:训练数据、模型测试和监控,以及结果的可解释性。

  1. 确保训练数据不带有偏见

自数据科学开始以来,我们的口号之一就是做出“数据驱动的决策”。但正如我们所知,数据可能是不完整的、垃圾的或完全错误的,这是一大危险,可能导致 AI 做出糟糕或有偏见的决策。使训练数据正确且完整,包括确认和否认的事实,是消除确认偏差的前提。

例如,假设我们构建一个模型来预测订阅者的增长。除了寻找与订阅者相关的特征外,是否探索过与非订阅者相关的特征?是否有些特征同时对订阅和非订阅有所贡献?训练数据是否限制或偏离了我们的预测和决策?

确保训练数据中所有方面的事实得到均等代表是确保 AI 不继承人类偏差的关键步骤之一。由于 AI 模型依赖于人类收集和整理的数据,而人类倾向于有确认偏差,因此在设计训练模型时,确保数据包含正面和负面场景是必须的,以确保模型没有偏差。然而,这通常涉及不同的数据来源,并需要多种数据收集和整理方法。在某些情况下,如果对立数据不存在或收集成本较高,数据合成可能是模拟对比场景的解决方案。

2. 通过彻底测试和验证来防止偏差

机器学习和人工智能已经具备自动测试过程来验证模型。然而,验证的目的通常围绕预测的可重复性、确保模型泛化能力而不出现过拟合,以及从统计分布中移除异常值。防止确认偏差需要额外步骤来验证训练集和模型的行为及输出。例如,模型能否同时确认和反驳一个假设?由于负面案例样本较少,是否存在任何后果或异常?是否由于人类干预认为不重要而导致某些特征被低估?

确认偏差的识别不是一次性的任务。在不断变化的世界中,新的负面或矛盾的事实可能会意外出现。最近的例外情况可能在未来成为新的常态。数据整理中的例外处理程序应定期检查,以确定是否删除了实际的相反案例。此外,应该定期进行审计和测试,以确保在模型发布后没有引入偏差。

3. 演示“思考”过程

从人类经验来看,我们的思维过程和心理模型对做出正确的决定至关重要。我们应该评估和理解 AI 模型如何得出决定或结论。AI 的一个明显优势是它可以让许多数据科学家和工程师同时合作评估其决策过程,而人类只能在个体的思维中单独进行。

然而,神经网络和深度学习模型以难以解释而闻名。鉴于此,可能需要推理过程和混合方法来理解一个决定或结论是否存在偏差:

  1. 彻底了解训练数据的来源、处理方式以及如何用于模型。

  2. 使用特定过程和可用库(例如,LIME — 局部可解释模型无关解释,SHAP — Shapley 加性解释)提高模型的可解释性。

  3. 利用可视化(例如图表)来展示不仅仅是最终结果,还包括从源数据到训练和模型执行的全过程,例如训练数据的质量、支持每个决策的参数实例、输出类别随时间的一致性、过程中的任何异常或离群点等。通过这种方式,数据工程师和数据科学家更容易识别模型可能在哪个步骤出现偏差,以及还需要哪些数据或训练。

结论

在历史上,人类一直擅长发明工具以克服自身的局限性和约束。鉴于人类和 AI 智能之间的相似性和差异性,我们应关注 AI 如何补充人类智能的不足,并防止人类的认知偏差。虽然人类难以克服这些偏差,但数据科学和 AI 可以帮助我们识别并最小化这些偏差,同时使过程更加透明。尽管本文重点讨论了确认偏差,但类似的原则和方法也可以应用于解决其他认知偏差。

AI 真的能帮你通过面试吗?

原文:towardsdatascience.com/can-ai-really-help-you-at-passing-interviews-22bce4a57a2

思考、提示和一些建议

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Daniel Rizea

·发布在 Towards Data Science ·9 分钟阅读·2023 年 8 月 5 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Andertoons 图像许可证

最近,我听到了一些面试官的担忧,他们担心候选人可能会利用 AI 来通过技术面试。担忧在于使用像 ChatGPT 或 Bard 这样的 LLM 技术,候选人可能会“作弊”并在技术面试中解决问题。

我认为你应该利用 AI来通过面试,但不是你最初所期待的那种方式。

通过面试最重要的因素是充分准备,而准备的最佳方式就是练习。

一些公司会收取数千美元,通过模拟面试提供反馈,并指出需要改进的地方。这为那些无法负担这种服务的人创造了巨大的机会差距。

随着新型 LLM 技术的出现,问题在于 AI 是否在平衡竞争的条件,是否可以作为练习模拟面试的导师。首先,让我们深入探讨一下利用 AI 的错误方式。

错误的方式

首先,让我们试着解决这个有效的问题。在面试中,你是否应该使用 LLM 服务(可以是 ChatGPT、Bard——随便你)来尝试获得技术问题的答案?技术是可行的,但真正的问题是你作为候选人是否真的应该这样使用?

在我看来,答案是。这样做会在短期和长期内伤害到你。让我们来看一下不这样做的一些原因:

你会被抓住

面试很有压力,大多数情况下,面试官会察觉到你在分屏操作、试图搜索答案并说出你不完全理解的内容。

我在我的职业生涯中进行过超过 1000 次面试,在一些情况下,候选人试图进行分屏操作,同时在与我交谈时寻找答案。这一点非常明显。

我怎么知道他们在寻找答案?他们不会注意我的暗示,会突然停顿,然后从不同的角度开始说话。

面试非常有压力。额外的压力和担心自己会被抓住会显著降低你的智商。

最可能的结果是你会失败面试。我见过几次这种情况。你可能非常聪明且勤奋,但一旦作弊,你就不会成为团队中的文化补充——任何团队。

面对面做不到的事

在 COVID 之前,大多数面试都是面对面的。大科技公司会为现场面试安排航班。随着 COVID 的出现,这一点有所变化,但现在随着返回办公室,越来越多的面试将会面对面进行。在这一点上,如果你被邀请到现场,使用 LLMs 在面试中解决问题几乎是不可能的。

游戏的错误角度

即使你成功获得了工作,你在新职位上很可能会遇到困难。你可以试图说服自己,只要进入岗位,就能在过程中解决一切,但你会给自己带来很多压力,因为你心里知道你在面试中作弊了。

这就像是以谎言开始一段关系——这很可能不会有好的结局。

更好地利用 AI 的方法

看起来 LLMs 在聊天互动方面非常擅长,这正是名字中的意思:大型语言模型。你很可能已经尝试过某个版本的 ChatGPT 或 Bard。如果没有,我鼓励你尝试一下。

从到目前为止大家做的实验来看,LLMs 在正确的提示方式下可能会成为非常好的导师。辅导和获得专业公司提供的服务来指导或教你学习技能是相当昂贵的,但现在借助 AI,事情可能会变得免费。

现在你可以使用 LLMs、今天的 ChatGPT 和 Bards 来完善你的技能,提升面试表现。

来自 AI 行业的一些技巧和窍门

在 LLMs 的帮助下,出现了一种新的“学科”,即所谓的提示工程,这是“明确你要求你的 AI LLM 模型提供什么”的聪明名称,以便你获得所需的答案。

目前在行业中关于提示工程有一些陷阱,你可以利用这些陷阱来获得更好的结果。是的,AI 确实会出现幻觉,这是一种巧妙的说法,指的是偏离正轨并给出错误的答案。在这里,良好的提示工程能够减少幻觉的可能性。我会尝试引用不同的文献,以便你看到我并不是在凭空捏造这些内容,你也可以深入研究,否则,你可以直接使用这些提示。

上下文,上下文,上下文

你可能听到过无数次,但上下文很重要。LLMs 也是如此。你为 LLM 引擎设置的上下文越好,你获得的答案就会越好。

逐步方法更好

同样适用于面试。面试官希望看到你为达到特定结果所采取的步骤。如果你在提示中要求提供逐步答案,你会更有可能得到不出现幻觉的模型,并获得更准确的结果。

这在行业中也被称为[思维链推理](https://ai.googleblog.com/2022/05/language-models-perform-reasoning-via.html)(零样本 CoT)。你可以通过在提示的末尾附加一个*“让我们一步一步思考”*来实现这一点。

LLMs 擅长自我检查

出于某种原因,即使 LLM 出现幻觉并且你询问模型根据你的初始问题答案是否正确,它通常也会知道答案错误并给出正确答案。如果它们擅长检查自己的答案,它们也擅长检查你的答案

LLMs 不擅长数学

LLMs在基本算术上表现不佳因此尽量避免这些主题。

除非你想通过微积分和基本算术的面试,否则这应该没问题。

但这些技术细节说够了,让我们看看如何将其付诸实践并融入一些之前的行业经验。随意实验你的文本提示。

模拟面试脚本和应用提示技巧

让我们看看如何将你的 LLM 聊天伙伴转变为面试官,带你进行模拟演示。下面是模拟面试过程中主要部分的详细介绍。

闲聊

这是为了让候选人放松并描述过程。我们在这里不需要任何提示,或者你可以和你的 LLM 进行关于天气的友好聊天,随你选择。

目前没有提示。

向候选人展示问题

在这里我们可以使用以下提示来生成一些可能的 Java 面试问题:

LLM prompt: “You are an interviewer with a FAANG tech company. 
What is a list of algorithmic problems to choose from in order to assess if a candidate is a good technical fit. 
The candidate’s preferred language is Java.

ChatGPT 示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的图片

不要忘记,提供背景信息是有帮助的。通常,问题分为算法或系统设计阶段,你可以通过改变提示中的术语来选择训练哪种类型。

现在你可以选择你的问题,假设我们选择 回文算法问题

LLM prompt: “Please present the palindrome problem to the candidate.

ChatGPT 示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的图片

与候选人一起讨论解决方案,就像在面试中一样

在这里你需要打开一个 Google 文档(在远程面试中,你很可能会有一个与面试官共享的书写解决方案的介质)。你可以开始起草你的解决方案和代码,并大声思考,就像在面试中一样。

如果你需要更多提示,可以请求它们

LLM prompt: "Can you give additional hints and examples without giving the solution?" 

时间到

当时间到时,评估解决方案并给予候选人宝贵的反馈。完成你认为有效的解决方案后,检查它是否有效。在下面的提示之后,将代码复制并粘贴到 LLM 提示中。不要忘记应用之前的技巧并请求逐步分析。

LLM prompt:"Is this a good solution for the Palindrome problem that the candidate has provided? Let's go through it step by step."

我们有以下问题的解决方案,其中我们 故意添加了 2 个错误 来看看引擎是否会发现它们:

  • 将正确的 length(cleanedInput) -1 改为 length(cleanedInput) -2

  • 将正确的 right — 改为 right ++

public class Palindrome {
public static boolean isPalindrome(String input) {
String cleanedInput = removeSpacesAndPunctuation(input);
cleanedInput = convertToLowercase(cleanedInput);
int left = 0;
int right = cleanedInput.length() - 2;
while (left < right) {
if (cleanedInput.charAt(left) != cleanedInput.charAt(right)) {
return false; // Characters don't match, not a palindrome
}
left++;
right++;
}
return true; // All characters matched, it's a palindrome
}
public static String removeSpacesAndPunctuation(String input) {
StringBuilder cleanedInput = new StringBuilder();
for (char c : input.toCharArray()) {
if (Character.isLetterOrDigit(c)) {
cleanedInput.append(c);
}
}
return cleanedInput.toString();
}
public static String convertToLowercase(String input) {
return input.toLowerCase();
}
public static void main(String[] args) {
String input = "A man, a plan, a canal: Panama";
System.out.println(isPalindrome(input)); // Output: true
}
}

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的图片

很高兴我们还得到了一些关于我们犯的错误的指点。

记住,减少 LLM 幻觉机会的一种方法是利用逐步分析方法或 CoT 通过请求逐步分析。

从回文示例中学习后,你可以继续研究另一个问题。

你还可以让 LLM 检查之前提供的答案,以确保它是正确的,并逐步进行分析。

LLM prompt: Are you sure that you have provided a correct assessment? Let’s go through it step by step.

LLMs 和模拟面试的局限性

即使应用了展示的技巧和窍门,LLMs 仍可能会产生幻觉并认为错误的解决方案看起来不错。最好的办法是进行事实核查。将代码运行在模拟器中,以查看它是否输出正确的答案。

使用 LLMs 的一种方法是提出面试中会问到的问题。作为一个很好的起点,你可以使用 LLM 模型解决问题,并通过运行实际代码或在线搜索解决方案来进行事实核查。

可能有帮助的工具

如果你不想自己实验 LLM 聊天引擎,你可以利用现有的 语音和聊天工具,这些工具可以让你在面试中更自如。

Google 提供了一些很酷的面试准备工具:interview-warmup

使用 AI 进行学习,而不是“游戏”

面试的目的在于评估你是否具备必要的技能以及是否与公司文化相匹配。操控系统不会让你与许多公司的文化契合,也很可能不会帮你获得工作。

你可以利用人工智能获得竞争优势,通过更快、更聪明地学习以及准备面试。这样你将提升你的价值,并能够通过任何面试,获得你想要的职位。

AI 能解决你的问题吗?

原文:towardsdatascience.com/can-ai-solve-your-problem-415c9bc1da8a?source=collection_archive---------7-----------------------#2023-11-27

识别 AI 适用项目想法的三个简单启发式方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Daniel Bakkelund

·

关注 发表在 Towards Data Science · 6 分钟阅读 · 2023 年 11 月 27 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 TheDigitalArtist 提供,来源于 pixabay

在一个旨在将 AI 能力融入其产品和服务的产品组织中,总是面临着让非 AI 领域专家也能参与到 AI 进程中的挑战。虽然不是每个人都需要成为 AI 专家,但必须尽可能多地让人们贡献想法,并探索利用 AI 的力量将公司推向更高水平。这一点尤其适用于领域专家和产品人员,他们对其产品和服务试图解决的问题了如指掌,并且知道问题的关键所在。

我学到的一个普遍存在的挑战是基本问题“我们可以用 AI 解决哪些问题?”。当非专家提出这个问题时,答案竟然很难给出。因此,我设计了三个启发式问题,你可以在面对一个问题时使用这些问题,思考“这个问题可以用 AI 解决吗?”。如果你能对这三个问题都回答“是”,你可能会发现自己有机会启动一个 AI 项目。

问题 1:你能说出来吗?

你可以把 AI 想象成一个回答问题的预言者。你需要问自己的是:

你能用文字表达你希望得到解答的问题吗?

这当然是一个适用于任何你想做的事情的测试。如果你想做某件事,但无法明确表达你想做的是什么,你可能并不真正知道自己想要什么。启动一个 AI 项目也不例外。

向 AI 提问的示例问题可能包括:

  • 这张图片中有一只狗吗?

  • 明天的天气会是什么?

  • 下周的乐透号码是什么?

这些都是可以提问的良好问题。但并不是所有的问题都能得到回答,因此我们需要另一个测试。

问题 2:它存在吗?

我们可以把预言者看作一个将问题映射到答案的函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预言者函数将问题映射到答案。

左侧的圆圈包含所有问题,而右侧的圆圈包含所有答案。预言者是将问题发送给答案的函数。接下来要问自己的是:

这个函数存在吗?

这可能看起来很奇怪,而且问题还会变得更加奇怪:你应该从形而上学的层面来问这个问题——理论上这个函数是否有可能存在?让我们举几个例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可能的预言者函数及其存在。

我们都见过 AI 回答“图片中的狗”这个问题,所以我们知道这个函数是存在的。我们也见过天气预报,所以我们知道在某种程度上可以预测明天的天气。但没有办法预测下周的乐透号码。原因在于,乐透被操控的目的正是为了使这个函数不存在。这是不可能的。这就是我所说的“在形而上学层面上”。

为什么这很重要?因为机器学习(这就是我们如何制作 AI)是通过从示例中学习来尝试近似函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

描绘的预言者函数以及它基于 AI 的近似。

如果我们有很多关于函数(即预言者)应如何行为的示例,我们可以尝试学习这种行为,并尽可能地模拟它。但你只能近似一个存在的函数。

诚然,这些都比较抽象,因此我建议将这个启发式方法替换为以下的元启发式方法:

一个知识丰富的人能做这件事吗?

从形而上学的角度来看,假设拥有世界上所有的信息和无限的时间,人类能否回答这个问题?显然,人类在识别图片中的狗方面做得相当好。人类确实开发了天气预报,并且也进行天气预报。但是,我们无法预测下周的乐透号码。

如果你已经走到这一步,回答了两次“是”,那么你有 1)一个明确的问题,以及 2)你知道至少在理论上,这个问题是可以回答的。但还有一个问题需要解决:

问题 3:背景信息是否可用?

这个问题稍微有点技术性。关键在于,预言者函数通常需要比单纯的问题更多的信息来找到答案。有知识的人在担任预言者时,可能需要额外的信息来做出决策或提供答案。这就是我所说的背景信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预言者函数和背景信息一起工作。背景信息通常包含超出问题本身的信息。

例如,天气预报的预言者需要知道当前的气象条件以及几天前的条件才能做出预测。这些信息不包含在短语“明天的天气会是什么?”中。

另一方面,在狗和猫的图片中,背景信息就在图片中,不需要额外的背景信息。

之所以这很重要,是因为当我们训练 AI 时,AI 会被问到如下类型的问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AI 训练问题。图片由 brgfx 提供,来源于 Freepik

然后,AI 会在收到真实答案之前做出猜测,并希望随着时间的推移,AI 能够学会区分猫和狗。但要实现这一点,差异必须是可用的,以便 AI 能学会识别这些差异。在图片的情况下,这很直接——你只需要确保图片的质量足够高,以使区分成为可能。在天气预报的情况下,变得更复杂——你实际上需要做出明智的决定,以确定进行天气预测所需的信息。这是一个最好由领域专家回答的问题,因此你可能需要寻求帮助,以获得一个好的答案。

但关键是:如果没有足够的信息供有知识的人回答这个问题,那么 AI 学会如何回答这个问题的希望也很小。你需要这些背景信息。

结论

总结一下,如果你希望测试你的 AI 项目想法,以确定这是否是一个可以通过 AI 解决的问题,你可以尝试回答以下三个问题:

1. 你能把你的问题用文字表达出来吗?

2. 有知识的人能完成这项工作吗?

3. 背景信息是否可用?

如果你能对这三个问题都回答“是”,那么你已经准备好继续前进了。可能仍然会有障碍需要克服,也许最终会发现太困难了。但那是另一个帖子的主题。

祝好运!

诚挚的问候

丹尼尔·巴克伦德

LLM 能否取代金融科技经理?开发无 GPU AI 工具进行企业分析的综合指南

原文:towardsdatascience.com/can-an-llm-replace-a-fintech-manager-comprehensive-guide-to-develop-a-gpu-free-ai-tool-for-corpo-ce04e12138e8

实践教程

开发你自己的零成本 LLM 包装器,以在本地解锁企业上下文

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Gerasimos Plegas 〽️

·发表于Towards Data Science ·9 分钟阅读·2023 年 12 月 20 日

“在孤独中,心灵获得力量,学会依赖自己” | 劳伦斯·斯特恩

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Daniel Eliashevskyi提供,来源于Unsplash

过去不到一年,GPT 星尘 ✨几乎涵盖了全球的各个领域。越来越多的专家,无论来自哪个领域,都渴望利用大型语言模型(LLM)来优化他们的工作流程。显然,企业界也不能缺席这一新趋势的探索。未来承诺着前所未有的可能性,但这些都伴随着适当的…成本。

本项目的范围是演示如何利用 LLM 的端到端解决方案,以减轻隐私和成本问题。我们将使用LLMWare,一个用于工业级企业 LLM 应用开发的开源框架,检索增强生成(RAG)方法[1],以及BLING——一组新推出的开源小模型,完全依赖 CPU 运行。

概念

在成功预测 Jrue Holiday 的 🏀 转会 到密尔沃基雄鹿后,Data Corp 开始了一个新项目:协助一家金融科技中小企业优化其决策过程。也就是说,构建一个工具来处理数百万份专有文档,查询先进的 GPT 类模型,并为经理提供简洁、优化的信息。这一切很好,但有两个主要陷阱:

  1. 安全性: 查询商业 LLM 模型(即 GPT-4)本质上意味着通过互联网共享专有信息(那那些数百万份文档怎么办?)。数据泄露无疑会损害公司的完整性。

  2. 成本: 像上面提到的自动化工具将提高经理们的生产力,但天下没有免费的午餐。预计的每日查询可能达到数百次,考虑到‘GPU-饥渴’的 LLM,累积的成本可能很容易失控。

上述限制促使我选择了一个棘手的替代方案:

如何开发一个能够处理专有知识并利用 LLM 模型的定制工具,但能够在本地(内部部署)运行,几乎不花费成本?

为了更好地传达结果,做出了几个假设:

#1: 公司专注于资产管理子领域,因此我们将查询相关话题:例如资产criticality

#2: 为了简化起见,我们将使用少量文档(3)来代表公司的专有来源。doc_1 部分描述了术语“criticality”,doc_2 包含了“critical”的词条,但意义不相关,doc_3 完全不相关。

为了完成任务,我们必须提取有关主题术语“credibility”的最佳上下文。然后,为了验证,我们将直接将其与 OpenAI 的 ChatGPT 的相应答案进行比较。

操作模式

  1. 熟悉关键概念,如 RAG 和 BLING 模型的应用。

  2. 环境设置和测试以运行代码。

  3. 工具开发,包括向量数据库初始化、嵌入模型选择、针对有效 RAG 的语义查询。

  4. 基准测试结果与 OpenAI 模型;与 GPT-3.5-turbo 输出进行比较。

1. 关键概念

在深入实施之前,熟悉基础知识是必要的。

嵌入

原始文档的文本必须转化为向量表示,这对执行相关性搜索至关重要。简而言之,这种元素使得机器学习模型能够找到它们之间的相似性,从而更好地理解原始数据(即单词)之间的关系。这种转换是通过使用嵌入模型[2]来完成的。

RAG

检索增强生成(RAG)是自然语言处理(NLP)领域的一个综合方法,以双重方式运作:

  • 检索相关文档中的信息

  • 生成基于这些信息的响应。

其实现涉及到用户希望从基础模型之外检索数据的情况,然后将其添加到上下文中以增强他们的提示[3]。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

工作流图片由作者提供

如上所示,用户查询触发了知识库的相关上下文检索——这是 RAG 模型的工作。然后,这些上下文增强了原始提示,现已增强的提示则输入到基础 LLM 模型中。

BLING 模型

这完全是一个便捷的开源小型模型(1B-3B 参数),经过优化以实现 RAG(检索增强生成)实施,旨在运行在基于 CPU 的基础设施上。它们由 HuggingFace 开发,针对知识密集型行业(即金融、法律、监管等),其实现涉及必须严格保护的敏感数据——这实际上是我们的企业案例!

现在我们了解了工具背后的基本技术细节,让我们开始编程吧!

2. 环境设置

在这一部分,我们将建立运行代码所需的环境。在命令行界面(CLI)中,只需运行以下代码片段:

  • 安装transformers —— 一个开源的预训练模型工具包,能够在多个模态上执行任务。它提供了快速下载和使用模型的 API。

  • 安装llmware框架 —— 一个企业级基于 LLM 的开发框架,提供工具和微调模型,包括检索库。

install.py

  • 安装Docker —— 一个容器化软件,允许我们从 LLMWare 运行一个 compose 文件,包括所有必要的工具,如Milvus向量数据库和MongoDB

docker_compose.bash

  • 导入库

import.py

为了确认设置,你可以按照LLMWare的快速入门指南,或选择直接运行以下代码(现在,让它完全运行 - 我们稍后会解释一切):

test_query.py

输出,包括查询结果,表明你已经成功设置了机器。让我们继续下一部分吧!

3. 工具开发

ℹ️ For your reference ℹ️
This code has been executed on a MacBook Pro 2,3 GHz Quad-Core i5
with 8BG RAM, which is anything but powerful for our days, yet managed 
to perform well.

现在,让我们进入有趣的部分——动手实践吧!

步骤 1 - 向量数据库

首先,我们必须创建一个数据库来存储我们的企业文本。这些信息在多维空间中表示为向量(嵌入),能够存储它们的数据库属于向量数据库的范畴[4]。

Milvus 是我们将要使用的开源解决方案,它将帮助我们对公司的文档执行语义查询。我们只需创建一个文件夹并将这些文档移动到那里。然后只需复制以下代码片段中的 samples_path

vector_db.py

第二步 - 嵌入模型

正如预期的那样,嵌入将被定位……由于我们将工具应用于资产管理领域,我们可以选择一个相关的嵌入模型。希望 HuggingFace 提供了一个专门构建的模型,名为:[industry-bert-asset-management](https://huggingface.co/llmware/industry-bert-asset-management-v0.1)。这是一个基于 BERT 的行业领域 Transformer,专为资产管理行业中的嵌入设计。

embeddings.py

第三步 - 语义查询

接下来,我们构造我们的语义查询,并将其传递通过向量数据库,要求返回 2 个结果。为了简化起见(参见假设 #1),要执行的查询是:“什么被定义为关键性?”

semantic_search.py

第四步 - BLING 模型

获取源数据后,我们将把它传递给选择的 BLING 模型。

首先,我们设置一个变量 embedded_text 来存储从 query_res 列表中的项拼接得到的最终文本。接下来,我们从 LLMWare 实例化一个 Prompt 对象(prompter),以克服严格的提示结构。然后,我们检查所有相关的 HuggingFace models 以实现最佳性能。

rag.py

为了更清楚,我在此描述了一个精简版本的输出,包括模型-回答对:

 > Loading Model: llmware/bling-1b-0.1...
LLM Response:  The product of the consequence of failure and likelihood of failure ratings provides the overall
criticality score for a given asset. The higher the score, the greater risk

 > Loading Model: llmware/bling-1.4b-0.1...
LLM Response:  The product of the consequence of failure and likelihood of failure ratings provides assertions
for the overall criticality score.

 > Loading Model: llmware/bling-falcon-1b-0.1...
LLM Response:   Criticality scores are the product of the consequence of failure and likelihood of failure ratings.
Criticality scores provide an informed prioritization process that not only identifies the highest risk assets, 
but also allows for the comparison of risk reduction options.

 > Loading Model: llmware/bling-cerebras-1.3b-0.1...
LLM Response:  Criticality score (risk score) for a given asset.

 > Loading Model: llmware/bling-sheared-llama-1.3b-0.1...
LLM Response: Criticality score

 > Loading Model: llmware/bling-sheared-llama-2.7b-0.1...
LLM Response: Criticality is the product of consequence of failure and likelihood of failure ratings, which provides the
overall risk score for a given asset.

 > Loading Model: llmware/bling-red-pajamas-3b-0.1...
LLM Response: The product of the consequence of failure and likelihood of failure ratings provides the overall criticality
score for a given asset.

注意:由于模型的随机性质,您的结果可能会有所不同。

4. 验证

起初,明智的做法是展示涉及的文档对“关键性”术语的说明。根据假设 #2,只有 doc_1 是相关的,并且说……

Criticality is the measure of risk associated with an asset.
Knowing which assets are more critical than others can aid in determining:
- how to prioritize the spending of limited funds;
- where to deploy limited personnel resources;
- how to manage an individual asset or collection
- capital improvement planning decisions.

To identify which assets are critical, two questions are important:
- How likely is the asset to fail (likelihood or probability of failure)?
- What are the consequences if the asset does fail (consequence or impact of failure)?

CRITICALITY SCORE
The product of the consequence of failure and likelihood of failure ratings provides 
the overall criticality score (risk score) for a given asset. The higher the score, the greater risk.

鉴于此,很容易得出结论,除了 *llmware/bling-falcon-1b-0.1*,其他模型的表现均不尽如人意,该模型包含了数学评估(即产品)和优先级语义:

> Loading Model: llmware/bling-falcon-1b-0.1...
LLM Response:   Criticality scores are the product of the consequence of failure and likelihood of failure ratings.
Criticality scores provide an informed prioritization process that not only identifies the highest risk assets, 
but also allows for the comparison of risk reduction options.

与 GPT-3.5-turbo 的基准测试

在设置好我们的 OpenAI 密钥后,我们可以使用任何所需的模型(在我们的例子中是 GPT-3.5)和添加 query_resultsprompter。这样,我们就可以准备好用源和查询字符串对 LLM 进行查询。

validate_gpt.py

In the context of an asset management, criticality is defined by the
importance of an asset to the organization's operations, financial well-being, 
and strategic objectives. It considers the asset's impact on production,
revenue generation, regulatory compliance, and overall business continuity.
Critical assets are prioritized for strategic planning, resource allocation, 
and risk mitigation efforts.

答案非常好,与我们工具的输出相比,推导结果令人非常满意。特别是,尽管我们的实现缺少了对资产重要性资源的简要参考,但它成功地包含了数学评估(也就是产品)和优先级语义,这些都源于专有文档。换句话说,这意味着我们那只有 1B 参数、在相当普通的笔记本电脑上本地运行的简陋模型,竟然能够与一个 20B 参数的原始 LLM 进行竞争!

结论

再一次,这是一次愉快的旅程……从零成本工具开始,利用最先进的开源框架如 LLMWare,我们轻松开发了一个隐私优先的 AI 工具用于上下文分析。

尽管我们使用了甚至是1/20 GPT-3.5-turbo 模型的小型 LLM,且完全不使用 GPU,但输出结果还是非常出色!我们敢于声称,我们的工具成功地从公司文档中提取了最重要的信息,并“有意识地”将其与 LLM 的响应相结合。

但最重要的是,这次尝试为克服与 GPU 相关的成本和隐私问题奠定了基础,尤其是在处理第三方商业 LLM 解决方案时。如果有任何事情是理所当然的,那就是企业——即使是小企业——可以从类似的实现中获得显著的好处。通过在本地运行,可能还使用专有 GPU 以获得额外的提升,它们可以优化其运营并赶上这一新的 LLM 热潮。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Andy Holmes提供,刊登在Unsplash

感谢阅读,祝您圣诞快乐!如果有任何问题,请随时在下面留言或通过𝕏 / LinkedIn与我联系。无论如何……

享受假期,克隆repo,并招聘下一个…… #LLM 😉

参考文献

[1] ai.meta.com/blog/retrieval-augmented-generation-streamlining-the-creation-of-intelligent-natural-language-processing-models/

[2] www.cloudflare.com/en-gb/learning/ai/what-are-embeddings/

[3] Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks, P. Lewis et al, 2020, arXiv:2005.11401

[4] www.pinecone.io/learn/vector-database/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值