openai-to-sqlite 作者 simonw

收藏

README 源代码

openai-to-sqlite

PyPI Changelog Tests License

这个工具提供了与 OpenAI API 交互并将结果存储到 SQLite 数据库中的实用程序。

请参阅 语义搜索答案:使用 GPT3 + OpenAI 嵌入对文档进行问答 了解此项目的背景信息。

有关使用此工具处理相关内容的教程,请参阅 使用 openai-to-sqlite 和嵌入存储和提供相关文档

安装

使用 pip 安装此工具

pip install openai-to-sqlite

配置

使用此工具需要 OpenAI API 密钥。

您可以在 https://beta.openai.com/account/api-keys 创建一个。

然后,您可以将 API 密钥设置为环境变量

export OPENAI_API_KEY=sk-...

或者使用 --token sk-... 选项将其传递给每个命令。

使用 SQL 函数调用 OpenAI API

openai-to-sqlite query 命令可用于执行调用 OpenAI API 的 SQL 查询。

可用的函数有

  • chatgpt(prompt) - 使用模型 gpt-3.5-turbo 调用 OpenAI Chat API 并使用指定的提示。
  • chatgpt(prompt, system) - 使用提示和指定的系统提示调用该 API。

将来计划增加更多函数。

以下是如何使用此命令对表中的内容运行基本情感分析:

openai-to-sqlite query database.db "
  update messages set sentiment = chatgpt(
    'Sentiment analysis for this message: ' || message ||
    ' - ONLY return a lowercase string from: positive, negative, neutral, unknown'
  )
  where sentiment not in ('positive', 'negative', 'neutral', 'unknown')
    or sentiment is null
"

这将更新名为 messages 的表中的 sentiment 列。它会使用指定的提示的响应填充该列。

该命令将显示一个进度条,指示正在处理的行数。

您可以使用 sqlite-utils 向表中添加一个空的 sentiment 列,如下所示:

sqlite-utils add-column database.db messages sentiment

嵌入

embeddings 命令可用于计算和存储文本字符串的 OpenAI 嵌入

每次嵌入都有成本,因此请务必熟悉该嵌入模型的定价

该命令可以通过四种不同的方式接受数据:

  • 作为包含对象列表的 JSON 文件
  • 作为 CSV 文件
  • 作为 TSV 文件
  • 通过对 SQLite 数据库运行查询

对于所有这些格式,都应该有一个 id 列,后跟一个或多个文本列。

ID 将作为内容 ID 存储。任何其他列将连接在一起用作要嵌入的文本。

API 返回的嵌入将作为二进制 Blob 保存到指定的 SQLite 数据库的 embeddings 表中 - 如果您传递 -t/--table 选项,则保存到另一个表中。

JSON、CSV 和 TSV

给定一个这样的 CSV 文件:

id,content
1,This is a test
2,This is another test

嵌入可以这样存储:

openai-to-sqlite embeddings embeddings.db data.csv

结果模式如下所示:

CREATE TABLE [embeddings] (
   [id] TEXT PRIMARY KEY,
   [embedding] BLOB
);

相同的数据可以以 TSV 数据形式提供:

id    content
1     This is a test
2     This is another test

然后这样导入:

openai-to-sqlite embeddings embeddings.db data.tsv

或以 JSON 数据形式提供:

[
  {"id": 1, "content": "This is a test"},
  {"id": 2, "content": "This is another test"}
]

这样导入:

openai-to-sqlite embeddings embeddings.db data.json

在每种情况下,工具都会自动检测数据格式。它通过检查数据本身来完成此操作 - 它不考虑文件扩展名。

如果自动检测不起作用,您可以传递 --format jsoncsvtsv 来明确指定格式:

openai-to-sqlite embeddings embeddings.db data.tsv --format tsv

从标准输入导入数据

您可以使用文件名 - 将数据通过管道输入到标准输入:

cat data.tsv | openai-to-sqlite embeddings embeddings.db -

来自 SQL 查询的数据

--sql 选项可用于从附加的 SQLite 数据库读取要嵌入的数据。查询必须返回一个 id 列和一个或多个要嵌入的文本列。

openai-to-sqlite embeddings content.db \
  --sql "select id, title from documents"

这将在 content.db 数据库中创建一个 embeddings 表,并使用根据该查询中的 title 列计算出的嵌入填充它。

您还可以将嵌入存储在一个数据库中,同时使用 --attach alias filename.db 选项从另一个数据库读取数据:

openai-to-sqlite embeddings embeddings.db \
  --attach documents documents.db \
  --sql "select id, title from documents.documents"

使用 --sql 时将显示一个进度条,指示计算嵌入可能需要的时间。

CSV/TSV/JSON 选项无法正确显示进度条。您可以通过先将数据导入到 SQLite (例如,使用 sqlite-utils),然后使用 --sql 运行嵌入来解决此问题。

分批处理

嵌入将以 100 个一批的形式发送到 OpenAI 嵌入 API。如果您知道您的数据是短字符串,可以使用 --batch-size 选项增加批次大小,最多可达 2048。

openai-to-sqlite embeddings embeddings.db data.csv --batch-size 2048

使用存储的嵌入

embedding 列是一个 SQLite blob,其中包含 1536 个浮点数,这些浮点数编码为 4 字节值的序列。

您可以在 Python 中将它们提取回浮点数数组,如下所示:

import struct

vector = struct.unpack(
    "f" * 1536, binary_embedding
)

使用 search 命令搜索嵌入

保存了内容的嵌入后,您可以使用 search 命令运行搜索。

openai-to-sqlite search embeddings.db 'this is my search term'

输出将是余弦相似度得分和内容 ID 的列表。

openai-to-sqlite search blog.db 'cool datasette demo'
0.843 7849
0.830 8036
0.828 8195
0.826 8098
0.818 8086
0.817 8171
0.816 8121
0.815 7860
0.815 7872
0.814 8169

如果您的嵌入存储在不同的表中,请添加 -t/--table 选项。

openai-to-sqlite search content.db 'this is my search term' -t documents

Add `--count 20` to retrieve 20 results (the default is 10).

使用 similar 命令搜索相似内容

保存了内容的嵌入后,您可以使用 similar 命令搜索相似内容。

oopenai-to-sqlite similar embeddings.db ''

输出将是余弦相似度得分和内容 ID 的列表。

openai-to-sqlite similar embeddings-bjcp-2021.db '23G Gose'
23G Gose
  1.000 23G Gose
  0.929 24A Witbier
  0.921 23A Berliner Weisse
  0.909 05B Kölsch
  0.907 01D American Wheat Beer
  0.906 27 Historical Beer: Lichtenhainer
  0.905 23D Lambic
  0.905 10A Weissbier
  0.904 04B Festbier
  0.904 01B American Lager

您可以传递多个 ID 来查看为每个 ID 计算的相似度。

openai-to-sqlite similar embeddings-bjcp-2021.db \
  '23G Gose' '01A American Light Lager'

或者传递 --all 来为数据库中的每个项目运行相似度计算。这会计算项目数量的平方次相似度,因此可能是一个耗时很长的操作。

openai-to-sqlite similar embeddings-bjcp-2021.db --all

将相似度计算结果保存到数据库

要将这些计算结果保存到数据库中的 similarities 表,请使用 --save 选项。

openai-to-sqlite similar embeddings-bjcp-2021.db --all --save

--save 选项会禁用输出。您可以使用 --print 重新启用输出。

openai-to-sqlite similar embeddings-bjcp-2021.db --all --save --print

要保存到数据库表中,而不是 similarities,请使用 --table

openai-to-sqlite similar embeddings-bjcp-2021.db \
  --all --save --table my_similarities

--recalculate-for-matches

重新计算数据库中每一行的相似度可能是一个相当耗时的操作。

如果您知道哪些行刚刚添加,可以使用 --recalculate-for-matches 加快速度。

这会告诉 openai-to-sqlite similar 只重新计算与指定行接近匹配的行的相似度。

这意味着您可以添加一两条额外的记录,然后触发更新已保存的相似度得分,仅针对这些新记录以及与这些新记录最接近的二十个匹配项,如下所示:

openai-to-sqlite similar embeddings-bjcp-2021.db \
  --save '23G Gose' '01A American Light Lager' \
  --recalculate-for-matches \
  --count 20 \
  --print

开发

要为此工具做贡献,请先检出代码。然后创建一个新的虚拟环境:

cd openai-to-sqlite
python -m venv venv
source venv/bin/activate

现在安装依赖项和测试依赖项:

pip install -e '.[test]'

要运行测试:

pytest