Embeddings:是什么以及它们为何重要?

Embeddings: 是什么以及它们为何重要

Embeddings是一个非常巧妙的办法,但常常包含在一堆令人生畏的专业术语中。

如果你能理解这些术语,他们就会解锁强大而令人兴奋的技术,这些技术可以应用于各种有趣的问题。

什么是向量嵌入?

向量嵌入是一项与更广泛的大型语言模型领域相关的技术——ChatGPT 和 Bard and Claude 背后的技术。

On the left, a blog entry titled Storing and serving related documents with oepnai-to-sqlite and embeddings. On the right, a JSON array of floating point numbers, with the caption Fixed zise: 300, 1000, 1536...

向量嵌入基于一个技巧:获取一段内容(在本例中为博客条目)并将该内容转换为浮点数数组。

该数组的关键在于,无论内容有多长,它的长度始终相同。长度由您使用的嵌入模型定义 - 数组的长度可能是 300、1,000 或 1,536 个数字。

思考这个数字数组的最好方法是将其想象为一个非常奇特的多维空间中的坐标。

1,536 维空间很难可视化,所以这里是相同想法的 3D 可视化:

a 3D chart showing a location in many-multi-dimensional space. 400 randomly placed red dots are scattered around the chart.

为什么要在这个 空间中 放置 内容 ?因为我们可以根据 内容 的位置(特别是附近的其他内容,类似于从你身边的朋友来了解你的信息)了解该内容的有趣信息。

人类无法直接理解这些嵌入中的值,但空间内的位置代表了实际内容的之间的某种语义含义。它可能会捕获已嵌入内容的颜色、形状、概念或各种其他特征。它可能会捕获已嵌入内容的颜色、形状、概念或各种其他特征。

没有人完全理解这些单独数字的含义,但我们知道它们的位置可用于查找有关内容的有用信息。

使用嵌入的相关内容

我使用嵌入解决的第一个问题是为我的 TIL 博客构建“相关内容”功能。我希望能够在每个页面的底部显示相关文章的列表。

我使用嵌入来完成此操作 - 在本例中,我使用了 OpenAI text-embedding-ada-002 模型,该模型可通过他们的 API 获得。

目前我的网站上有 472 篇文章。我计算了每篇文章的 1,536 维嵌入向量(浮点数数组),并将这些向量存储在我网站的 SQLite 数据库中。

现在,如果我想查找给定文章的相关文章,我可以计算该文章的嵌入向量与数据库中所有其他文章之间的余弦相似度,然后按距离返回 10 个最接近的匹配项。

本页底部有一个示例。使用 Geospatial SQL queries in SQLite using TG, sqlite-tg and datasette-sqlite-tg 查询的前五篇相关文章是:

这是一个符合要求得列表!

这是我用来计算这些余弦相似距离的 Python 函数:

def cosine_similarity(a, b):
    dot_product = sum(x * y for x, y in zip(a, b))
    magnitude_a = sum(x * x for x in a) ** 0.5
    magnitude_b = sum(x * x for x in b) ** 0.5
    return dot_product / (magnitude_a * magnitude_b)

我的 TIL 站点在我的 Datasette Python 框架上运行,该框架支持在 SQLite 数据库之上构建站点。我写了更多关于它如何在烘焙数据架构模式中工作的文章。

您可以浏览在 tils/embeddings 中存储计算的嵌入的 SQLite 表。

Screenshot of the embeddings table in Datasette, it has 472, rows each of which consists of a text ID and a binary 6.144 bytes embedding

这些是二进制值。我们可以运行此 SQL 查询以十六进制形式查看它们:

select id, hex(embedding) from embeddings

Running that SQL query in Datasette returns text IDs and long hexadecimal strings for each embedding

但这仍然不太可读。我们可以使用 llm_embed_decode() 自定义 SQL 函数将它们转换为 JSON 数组:

select id, llm_embed_decode(embedding) from embeddings limit 10

在这里尝试一下。它显示每篇文章都附有 1,536 个浮点数的数组。

Now the SQL query returns a JSON array of floating point numbers for each ID

我们可以使用另一个自定义 SQL 函数 llm_embed_cosine(vector1, vector2) 来计算这些余弦距离并找到最相似的内容。

该 SQL 函数在我的 datasette-llm-embed 插件中定义。

以下查询返回与我的 SQLite TG 文章最相似的五篇文章:

select
  id,  llm_embed_cosine(    embedding,  (  select
        embedding      from
        embeddings      where
        id = 'sqlite_sqlite-tg.md'
    )  ) as score
from
  embeddings
order by
  score desc
limit 5

Executing that query returns the following results:
执行该查询将返回以下结果:

idscore
sqlite_sqlite-tg.md1.0
sqlite_geopoly.md0.8817322855676049
spatialite_viewing-geopackage-data-with-spatialite-and-datasette.md0.8813094978399854
gis_gdal-sql.md0.8799581261326747
spatialite_knn.md0.8692992294266506

正如预期的那样,该文章与其自身的相似度为 1.0。其他文章都与 SQLite 中的地理空间 SQL 查询相关。

该查询的执行时间大约为 400 毫秒。为了加快速度,我预先计算了每篇文章的前 10 个相似之处,并将它们存储在一个名为 tils/similarities 的单独表中。

The similarities table has 4,922 rows each with an id, other_id and score column.

我编写了一个 Python 函数来从该表中查找相关文档,并从用于呈现文章页面的模板中调用它。

我的使用 openai-to-sqlite 和嵌入 TIL 存储和服务相关文档详细解释了这一切是如何工作的,包括如何使用 GitHub Actions 来获取新嵌入作为部署站点的构建脚本的一部分。

我在这个项目中使用了 OpenAI 嵌入 API。它非常便宜——对于我的 TIL 网站,我嵌入了大约 402,500 个token,按 0.0001 美元/1,000 个token 计算,相当于 0.04 美元——只需 4 美分!

它真的很容易使用:你向它 POST 一些文本以及你的 API 密钥,它会返回浮点数的 JSON 数组。

Screenshot of curl against api.openai.com/v1/embeddings sending a Bearer token header and a JSON body specifying input text and the text-embedding-ada-002 model. The API responds with a JSON list of numbers.

但是…这是一个专有模型。几个月前,OpenAI 关闭了一些旧的嵌入模型,如果您存储了这些模型的大量嵌入,这将是一个问题,因为如果您希望能够嵌入,则需要根据支持的模型重新计算它们还有什么新的东西。

Screenshot of the OpenAI First-generation text embedding models list, showing the shutdown date of 4th April 2024 for 7 legacy models.

值得称赞的是,OpenAI 确实承诺“承担用户使用这些新模型重新嵌入内容的财务成本。”——但这仍然是对依赖专有模型持谨慎态度的一个理由。

好消息是,有非常强大的开放许可模型,您可以在自己的硬件上运行它们,从而避免它们被关闭的任何风险。我们稍后会详细讨论这一点。

探索如何与 Word2Vec 一起使用

Google Research 10 年前发表了一篇有影响力的论文,描述了他们创建的名为 Word2Vec 的早期嵌入模型。

这篇论文是 Efficient Estimation of Word Representations in Vector Space,发表日期为 2013 年 1 月 16 日。这篇论文引发了人们对嵌入的广泛兴趣。

Word2Vec 是一个模型,它将单个单词转换为包含 300 个数字的列表。该数字列表捕获了相关单词的含义。

通过演示可以最好地说明这一点。

Turbomaze.github.io/word2vecjson 是 Anthony Liu 与 Word2Vec 语料库的 10,000 个单词子集组合而成的交互式工具。您可以查看此 JavaScript 文件以查看这 10,000 个单词的 JSON 及其关联的 300 长数字数组。

Screenshot of the Word to Vec JS Demo showing the results for france and the algebra results for germany + paris - france

搜索单词以根据与其 Word2Vec 表示形式的余弦距离查找相似单词。例如,单词“france”会返回以下相关结果:

wordsimilarity
france 法国1
french 法语0.7000748343471224
belgium 比利时0.6933180492111168
paris 巴黎0.6334910653433325
germany 德国0.627075617939471
italy 意大利0.6135215284228007
spain 西班牙0.6064218103692152

这是法国和欧洲地理的混合体。

您可以在这里做的一件非常有趣的事情是对这些向量执行算术运算。

获取“germany”的向量,添加“paris”并减去“france”。得到的向量最接近“berlin”!

这个模型的某些部分已经捕捉到了民族和地理的概念,以至于你可以使用算术来探索关于世界的更多事实。

Word2Vec 使用 16 亿字的内容进行训练。我们今天使用的嵌入模型是在更大的数据集上进行训练的,并且可以更丰富地理解底层关系。

使用我的 LLM 工具生成嵌入向量

我一直在构建一个名为 LLM 的命令行实用程序和 Python 库。

您可以在此处阅读有关 LLM 的更多信息:

LLM 是一个用于处理大型语言模型的工具。你可以像这样安装它:

pip install llm

或者通过自制程序:

brew install llm

您可以将其用作与 LLMs 交互的命令行工具,或用作 Python 库。

它开箱即用,可以与 OpenAI API 配合使用。设置 API 密钥,您可以运行如下命令:

llm 'ten fun names for a pet pelican'

真正有趣的是当你开始安装插件时。有些插件可以向其中添加全新的语言模型,包括直接在您自己的计算机上运行的模型。

几个月前,我扩展了 LLM 以支持也可以运行嵌入模型的插件。

以下是如何使用 LLM 运行标题醒目的 all-MiniLM-L6-v2 模型:

Slide showing the commands listed below

首先,我们安装 llm ,然后使用它来安装 llm-sentence-transformers 插件 - SentenceTransformers 库的包装器。

pip install llmllm install llm-sentence-transformers

接下来我们需要注册 all-MiniLM-L6-v2 模型。这会将模型从 Hugging Face 下载到您的计算机:

llm sentence-transformers register all-MiniLM-L6-v2

我们可以通过嵌入一个句子来测试它,如下所示:

llm embed -m sentence-transformers/all-MiniLM-L6-v2 \  -c 'Hello world'

这会输出一个 JSON 数组,其开头如下:

[-0.03447725251317024, 0.031023245304822922, 0.006734962109476328, 0.026108916848897934, -0.03936201333999634, ...

像这样的嵌入本身并不是很有趣——我们需要存储和比较它们才能开始获得有用的结果。

LLM 可以将嵌入存储在“集合”(SQLite 表)中。 embed-multi 命令可用于一次嵌入多条内容并将它们存储在一个集合中。

That’s what this next command does:
这就是下一个命令的作用:

llm embed-multi readmes \  --model sentence-transformers/all-MiniLM-L6-v2 \  --files ~/ '**/README.md' --store

在这里,我们正在填充一个名为“自述文件”的集合。

--files 选项有两个参数:要搜索的目录和与文件名匹配的 glob 模式。在本例中,我正在我的主目录中递归搜索任何名为 README.md 的文件。

--store 选项导致 LLM 除了嵌入向量之外,还将原始文本存储在 SQLite 表中。

该命令在我的计算机上运行大约需要 30 分钟,但它有效!我现在有一个名为 readmes 的集合,其中包含 16,796 行 - 它对应在我的主目录中找到的每个 README.md 文件。

基于 Vibes 的搜索

现在我们有了嵌入集合,我们可以使用 llm 类似命令对其进行搜索:

A terminal running llm similar and piping the results through jq

llm similar readmes -c 'sqlite backup tools' | jq .id

我们要求 readmes 集合中的项目类似于短语“sqlite backup tools”的嵌入向量。

该命令默认输出 JSON,其中包括 README 文件的全文,因为我们之前使用 --store 存储了它们。

通过 jq .id 管道传输结果会导致命令仅输出匹配行的 ID。

排名靠前的匹配结果是:

"sqlite-diffable/README.md"
"sqlite-dump/README.md"
"ftstri/salite/ext/repair/README.md"
"simonw/README.md"
"sqlite-generate/README.md"
"sqlite-history/README.md"
"dbf-to-sqlite/README.md"
"ftstri/sqlite/ext/README.md"
"sqlite-utils/README.md"
"ftstri/sqlite/README.md'

这些都是很好的结果!这些自述文件中的每一个都描述了用于处理 SQLite 备份的工具或以某种方式与备份相关的项目。

有趣的是,不能保证术语“backups”直接出现在这些自述文件的文本中。内容在语义上与该短语相似,但可能与文本不完全匹配。

我们可以称之为语义搜索。我喜欢将其视为vibes-based search。

根据单词含义的这种奇怪的多维空间表示,这些自述文件的氛围与我们的搜索词相关。

这非常有用。如果您曾经为网站构建过搜索引擎,您就会知道精确匹配并不总能帮助人们找到他们正在寻找的内容。

我们可以使用这种语义搜索来为一大堆不同类型的内容构建更好的搜索引擎。

使用 Symbex 嵌入代码

我一直在构建的另一个工具称为 Symbex。它是一个用于探索 Python 代码库中符号的工具。

我最初构建它是为了帮助快速查找 Python 函数和类,并将它们通过管道传输到 LLMs 中以帮助解释和重写它们。

然后我意识到我可以使用它来计算代码库中所有函数的嵌入,并使用这些嵌入来构建代码搜索引擎。

我添加了一项功能,可以输出表示找到的符号的 JSON 或 CSV,使用与 llm embed-multi 可以用作输入的相同输出格式。

以下是我如何使用新发布的名为 gte-tiny 的模型构建 Datasette 项目中所有函数的集合 - 只是一个 60MB 的文件!

llm sentence-transformers register TaylorAI/gte-tiny

cd datasette/datasettesymbex '*' '*:*' --nl | \  llm embed-multi functions - \  --model sentence-transformers/TaylorAI/gte-tiny \  --format nl \  --store

symbex '*' '*:*' --nl 查找当前目录中的所有函数 ( * ) 和类方法( *:* 模式),并将它们输出为换行符分隔的 JSON。

llm embed-multi ... --format nl 命令需要以换行符分隔的 JSON 作为输入,因此我们可以将 symbex 的输出直接通过管道传输到其中。

默认情况下将嵌入存储在默认的 LLM SQLite 数据库中。您可以添加 --database /tmp/data.db 来指定替代位置。

现在…我可以针对我的代码库运行基于振动的语义搜索!

我可以使用 llm similar 命令来执行此操作,但我也可以使用 Datasette 本身运行这些搜索。

这是一个 SQL 查询,使用之前的 datasette-llm-embed 插件:

with input as (  select
    llm_embed(      'sentence-transformers/TaylorAI/gte-tiny',      :input    ) as e)
select
  id,  content
from
  embeddings,  input
where
  collection_id = (    select id from collections where name = 'functions'
  )
order by
  llm_embed_cosine(embedding, input.e) desc
limit 5

:input 参数会被 Datasette 自动转换为表单字段。

当我运行它时,我得到与列出插件概念相关的函数:

Running that query in Datasette with an input of list plugins returns the plugins() function from the cli.py file on line 175

这里的关键思想是使用 SQLite 作为集成点——将多个工具组合在一起的基础。

我可以运行单独的工具,从代码库中提取函数,通过嵌入模型运行它们,将这些嵌入写入 SQLite,然后对结果运行查询。

现在,任何可以通过管道传输到工具中的内容都可以由该生态系统的其他组件嵌入和处理。

使用 CLIP 将文本和图像嵌入在一起

我目前最喜欢的嵌入模型是 CLIP。

CLIP 是 OpenAI 于 2021 年 1 月发布的一个令人着迷的模型,当时他们仍在公开地做大多数事情,可以嵌入文本和图像。

至关重要的是,它将它们嵌入到同一个向量空间中。

如果嵌入字符串“dog”,您将获得 512 维空间中的位置(取决于您的 CLIP 配置)。

如果您嵌入狗的照片,您将在同一空间中获得一个位置…并且它与字符串“dog”的位置的距离很接近!

这意味着我们可以使用文本搜索相关图像,也可以使用图像搜索相关文本

我构建了一个交互式演示来帮助解释其工作原理。该演示是一个 Observable 笔记本,直接在浏览器中运行 CLIP 模型。

这是一个相当大的页面 - 它必须加载 158MB 的资源(CLIP 文本模型为 64.6MB,图像模型为 87.6MB) - 但一旦加载,您可以使用它来嵌入图像,然后嵌入文本字符串并计算两者之间的距离。

我可以给它这张我拍的海滩照片:

A bright blue sky over a beach, with sandy cliffs and the Pacific ocean in the frame

然后输入不同的文本字符串来计算相似度得分,此处显示为百分比:

Animation showing different similarity scores for different text strings

text 文本score 分数
beach 海滩26.946%
city 城市19.839%
sunshine 阳光24.146%
sunshine beach 阳光海滩26.741%
california 加利福尼亚州25.686%
california beach 加利福尼亚海滩27.427%

令人惊奇的是,我们可以在浏览器中运行的 JavaScript 中完成所有这些工作!

有一个明显的问题:能够拍摄任意照片并说“这与‘城市’一词有多相似?”实际上并没有那么有用。

诀窍是在此基础上构建额外的接口。我们再一次有能力构建vibes-based search引擎。

这是其中一个很好的例子。

水龙头查找器:使用 CLIP 查找水龙头

Drew Breunig 使用 LLM 和我的 llm-clip 插件构建了一个水龙头搜索引擎。

他正在装修浴室,需要购买新水龙头。因此,他从一家水龙头供应公司收集了 20,000 张水龙头照片,并对所有这些照片运行 CLIP。

他使用该结果构建了 Faucet Finder——一个自定义工具(使用 Datasette 部署),用于查找与其他水龙头相似的水龙头。

The Faucet Finder homepage - six faucets, each with a Find Similar button.

除此之外,这意味着您可以找到您喜欢的昂贵水龙头,然后寻找视觉上相似的更便宜的选择!

德鲁在《寻找带嵌入的浴室水龙头》中详细介绍了他的项目。

Drew 的演示使用预先计算的嵌入来显示类似的结果,而无需在服务器上运行 CLIP 模型。

受此启发,我花了一些时间研究如何部署由我自己的 Fly.io 帐户托管的服务器端 CLIP 模型。

Drew’s Datasette instance includes this table of embedding vectors, exposed via the Datasette API.
Drew 的 Datasette 实例包含通过 Datasette API 公开的嵌入向量表。

我使用此 API 部署了自己的实例来嵌入文本字符串,然后构建了一个 Observable 笔记本演示,该演示可以访问这两个 API 并组合结果。

observablehq.com/@simonw/search-for-faucets-with-clip-api

现在我可以搜索“金紫色”之类的内容并获取vibes-based search的水龙头结果:

Observable notebook: Search for Faucets with CLIP. The search term gold purple produces 8 alarmingly tasteless faucets in those combined colors.

能够在几个小时内启动这种超特定的搜索引擎正是让我对将嵌入作为工具箱中的工具感到兴奋的技巧。

聚类嵌入

相关内容和基于语义/vibes-based search是嵌入的两个最常见的应用,但是您也可以用它们做很多其他巧妙的事情。

其中之一是聚类。

我为此构建了一个名为 llm-cluster 的插件,它使用 scikit-learn 中的 sklearn.cluster 来实现此功能。

为了证明这一点,我使用 paginate-json 工具和 GitHub issues API 将 simonw/llm 存储库中所有问题的标题收集到名为 llm-issues 的集合中:

paginate-json 'https://api.github.com/repos/simonw/llm/issues?state=all&filter=all' \  | jq '[.[] | {id: .id, title: .title}]' \  | llm embed-multi llm-issues - \  --store

现在我可以创建 10 个问题集群,如下所示:

llm install llm-clusterllm cluster llm-issues 10

簇以 JSON 数组的形式输出,输出如下所示(已截断):

[  {    "id": "2",    "items": [      {        "id": "1650662628",        "content": "Initial design"
      },      {        "id": "1650682379",        "content": "Log prompts and responses to SQLite"
      }    ]  },  {    "id": "4",    "items": [      {        "id": "1650760699",        "content": "llm web command - launches a web server"
      },      {        "id": "1759659476",        "content": "`llm models` command"
      },      {        "id": "1784156919",        "content": "`llm.get_model(alias)` helper"
      }    ]  },  {    "id": "7",    "items": [      {        "id": "1650765575",        "content": "--code mode for outputting code"
      },      {        "id": "1659086298",        "content": "Accept PROMPT from --stdin"
      },      {        "id": "1714651657",        "content": "Accept input from standard in"
      }    ]  }]

这些看起来确实相关,但我们可以做得更好。 llm cluster 命令有一个 --summary 选项,该选项使其通过 LLM 传递生成的簇文本,并使用它为每个簇生成描述性名称:

llm cluster llm-issues 10 --summary

这会返回“日志管理和交互式提示跟踪”和“持续对话机制和管理”等名称。有关更多详细信息,请参阅自述文件。

通过主成分分析进行二维可视化

大规模多维空间的问题在于它很难可视化。

我们可以使用一种称为主成分分析的技术将数据的维度减少到更易于管理的大小,结果表明较低的维度可以继续捕获有关内容的有用语义。

Matt Webb 使用 OpenAI 嵌入模型生成嵌入,用于描述 BBC 的 In Our Time 播客的每一集。他使用这些来查找相关剧集,同时还对它们运行 PCA 以创建交互式 2D 可视化。

Animated screenshot of a cloud of points in 2D space. At one side hovering over them shows things like The War of 1812 and The Battle of Trafalgar - at the other side we get Quantum Gravity and Higgs Boson and Carbon

将 1,536 维减少到只有 2 维仍然可以产生一种有意义的数据探索方式!有关历史战争的剧集彼此相邻,其他地方则有一系列有关现代科学发现的剧集。

Matt 在通过 Dewey 十进制代码浏览 BBC In Our Time 档案中写了更多相关内容。

使用 均值向量 对句子进行评分

嵌入的另一个技巧是使用它们进行分类

首先计算以某种方式分类的一组嵌入的 均值向量,然后将新内容的嵌入向量 与这些 均值向量 进行比较,以将其分配到一个类别。

Amelia Wattenberger 在“利用嵌入发挥创意”中展示了一个很好的例子。

她希望通过鼓励 具体和抽象句子的混合来帮助人们提高写作水平。但是如何判断文本句子是具体的还是抽象的呢?

她的技巧是生成两种类型句子的样本,计算它们的 均值向量,然后根据它们与新定义的频谱两端的接近程度对新句子进行评分。

A document. Different sentences are displayed in different shades of green and purple, with a key on the right hand side showing that green means concreete and purple means abstract, with a gradient between them.

该分数甚至可以转换为松散地表示给定句子的抽象或具体程度的颜色!

这是一个非常简洁的演示,展示了您可以在这项技术的基础上开始构建的创意界面。

用检索增强一代回答问题

我将以最初让我对嵌入感到兴奋的想法作为结束语。

每个尝试 ChatGPT 的人最终都会问同样的问题:我如何使用这个版本来回答基于我自己的私人笔记或我公司拥有的内部文档的问题?

人们认为答案是在该内容的基础上训练自定义模型,这可能会花费巨大的代价

事实证明这实际上没有必要。您可以使用现成的大型语言模型模型(托管模型或本地运行的模型)和一种称为检索增强生成(RAG)的技巧。

关键思想是:用户提出问题。您在私人文档中搜索与问题相关的内容,然后将该内容的摘录与原始问题一起粘贴到 LLM(遵守其大小限制,通常在 3,000 到 6,000 字之间)。

然后,LLM 可以根据您提供的附加内容回答问题。

这个廉价的伎俩却非常有效。获得此功能的基本版本很简单,挑战在于考虑到用户可能会问的无数问题,使其尽可能良好地工作。

RAG 中的关键问题是找出包含在 LLM 提示中的最佳内容摘录。

由嵌入提供支持的“基于 Vibes”的语义搜索正是您收集潜在相关内容以帮助回答用户问题所需的东西。

我根据我的博客内容构建了一个版本,详细描述见使用 E5-large-v2 嵌入我的博客段落。

为此,我使用了名为 E5-large-v2 的模型。这是一个根据具体用例进行训练的模型。

查找与问题相关的内容的一个挑战是,用户的问题“什么是 shot-scraper?”不能保证被认为在语义上与回答该问题的内容相似。问题和断言具有不同的语法。

E5-large-v2 通过支持两种类型的内容来解决这个问题。您可以在同一空间中嵌入短语(事实句子)和查询(问题),类似于 CLIP 支持图像和文本的方式。

我从博客中嵌入了 19,000 个文本段落作为短语,现在我可以嵌入一个问题作为查询,并使用它来查找最有可能回答该问题的段落。

结果是 RAG 作为单行 Bash 脚本实现:

llm similar blog-paragraphs -c "query: $1" \  | jq '.content | sub("passage: "; "")' -r \  | llm -m mlc-chat-Llama-2-7b-chat-hf-q4f16_1 \  "$1" -s 'You answer questions as a single paragraph'

此示例使用在我的笔记本电脑上运行的 Llama 2 Chat 7B(带有 llm-mlc 插件),因此我能够使用在我的笔记本电脑上运行的代码完全离线回答问题。

运行这个:

./blog-answer.sh 'What is shot-scraper?'

输出这个:

Shot-scraper 是一个包装 Playwright 的 Python 实用程序,提供命令行界面和 YAML 驱动的配置流程,用于自动执行网页屏幕截图并使用 JavaScript 从中抓取数据的过程。它可用于拍摄一次性屏幕截图,或通过在 YAML 文件中定义它们以可重复的方式拍摄多个屏幕截图。此外,它还可用于在页面上执行 JavaScript 并返回结果值。

这是对我的shot-scraper工具的一个很好的描述。我检查过,没有一个输出与我之前在博客上发布的内容完全匹配。

Q&A 问答

我的演讲以问答环节结束。以下是总结的问题和答案。

  • LangChain 如何融入其中?

    LangChain 是一个流行的框架,用于在 LLMs 之上实现功能。它涵盖了很多领域——我对LangChain 的唯一问题是你必须投入大量的工作来理解它是如何工作的以及它能为你做什么。检索增强生成是LangChain的关键功能之一,所以如果您投入精力,我今天向您展示的很多东西都可以构建在LangChain之上。

    我的理念与 LangChain 不同,我专注于构建一套可以协同工作的小工具,而不是一次性解决所有问题的单一框架。

  • **您是否尝试过余弦相似度以外的距离函数? **

    我没有。余弦相似度是其他人似乎都在使用的默认函数,我还没有花任何时间探索其他选项。

    实际上,我让 ChatGPT 跨 Python 和 JavaScript 编写了所有不同版本的余弦相似度!

    RAG 的一个令人着迷的地方是它有很多不同的旋钮可供您调整。你可以尝试不同的距离函数、不同的嵌入模型、不同的提示策略和不同的LLMs。这里有很大的实验空间。

  • 如果你有 10 亿个对象,你需要调整什么?

    我今天展示的演示都很小——最多大约 20,000 个嵌入。它足够小,您可以对所有内容运行强力余弦相似函数,并在合理的时间内返回结果。

    如果您要处理更多数据,有越来越多的选项可以提供帮助。

    许多初创公司正在推出新的“向量数据库”——这些数据库实际上是定制的,可以尽快回答针对向量的最近邻查询。

    我不相信您需要一个全新的数据库:我更兴奋的是向现有数据库添加自定义索引。例如,SQLite 有 sqlite-vss,PostgreSQL 有 pgvector。

    我还使用 Facebook 的 FAISS 库做了一些成功的实验,包括构建一个使用它的 Datasette 插件,称为 datasette-faiss。

  • ** 您很高兴看到嵌入模型的哪些改进?**

    我对多模式模型感到非常兴奋。 CLIP 是一个很好的例子,但我也一直在尝试 Facebook 的 ImageBind,它“学习跨六种不同模式(图像、文本、音频、深度、热和 IMU 数据)的联合嵌入。”看起来我们可以走得更远,而不仅仅是图像和文本!

    我也喜欢这些型号越来越小的趋势。我之前演示了一个新模型,gtr-tiny,只有 60MB。能够在受限设备或浏览器中运行这些东西对我来说真的很令人兴奋。

进一步阅读

如果您想更深入地了解嵌入如何工作的底层细节,我建议如下:


原文地址:Embeddings: What they are and why they matter

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值