diff --git a/br/backup-and-restore-overview.md b/br/backup-and-restore-overview.md index 3670b317ae64..2eefca83608a 100644 --- a/br/backup-and-restore-overview.md +++ b/br/backup-and-restore-overview.md @@ -120,6 +120,7 @@ TiDB 支持将数据备份到 Amazon S3、Google Cloud Storage (GCS)、Azure Blo | 全局临时表 | | 确保使用 BR v5.3.0 及以上版本进行备份和恢复,否则会导致全局临时表的表定义错误。 | | TiDB Lightning 物理导入模式| |上游数据库使用 TiDB Lightning 物理导入模式导入的数据,无法作为数据日志备份下来。推荐在数据导入后执行一次全量备份,细节参考[上游数据库使用 TiDB Lightning 物理导入模式导入数据的恢复](/faq/backup-and-restore-faq.md#上游数据库使用-tidb-lightning-物理导入模式导入数据时为什么无法使用日志备份功能)。| | TiCDC | | BR v8.2.0 及以上版本:如果在恢复的目标集群有 [CheckpointTS](/ticdc/ticdc-architecture.md#checkpointts) 早于 BackupTS 的 Changefeed,BR 会拒绝执行恢复。BR v8.2.0 之前的版本:如果在恢复的目标集群有任何活跃的 TiCDC Changefeed,BR 会拒绝执行恢复。 | +| 向量搜索 | | 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 | ### 版本间兼容性 diff --git a/dm/dm-overview.md b/dm/dm-overview.md index f4ef050d30d6..2c0d526279da 100644 --- a/dm/dm-overview.md +++ b/dm/dm-overview.md @@ -60,6 +60,10 @@ tiup install dm dmctl - DM 不支持 MySQL 8.0 的新特性 binlog 事务压缩 [Transaction_payload_event](https://dev.mysql.com/doc/refman/8.0/en/binary-log-transaction-compression.html)。使用 binlog 事务压缩有导致上下游数据不一致的风险。 ++ 向量类型数据同步 + + - DM 不支持 MySQL 9.0 的向量数据类型同步。 + ## Contributing 欢迎参与 DM 开源项目并万分感谢您的贡献,可以查看 [CONTRIBUTING.md](https://github.com/pingcap/tiflow/blob/master/dm/CONTRIBUTING.md) 了解更多信息。 diff --git a/media/vector-search/embedding-search.png b/media/vector-search/embedding-search.png new file mode 100644 index 000000000000..0035ada1b747 Binary files /dev/null and b/media/vector-search/embedding-search.png differ diff --git a/ticdc/ticdc-compatibility.md b/ticdc/ticdc-compatibility.md index 24d23d6ebf1c..ffe9026ef6ae 100644 --- a/ticdc/ticdc-compatibility.md +++ b/ticdc/ticdc-compatibility.md @@ -65,3 +65,11 @@ TiCDC 从 v5.3.0 开始支持[全局临时表](/temporary-tables.md#全局临时 你需要使用 TiCDC v5.3.0 及以上版本同步全局临时表到下游。低于该版本,会导致表定义错误。 如果 TiCDC 的上游集群包含全局临时表,下游集群也必须是 TiDB 5.3.0 及以上版本,否则同步报错。 + +### 向量搜索功能兼容性说明(实验特性) + +TiCDC 从 v8.4.0 开始支持[向量搜索功能](/vector-search-overview.md)。 + +写入下游为 Kafka 或者存储服务(如:Amazon S3、GCS、Azure Blob Storage 和 NFS)时,会将向量类型转为字符串类型。 + +写入到不支持向量类型的 MySQL 兼容数据库时, 涉及向量类型的 DDL 事件无法成功写入。在`sink-url`中添加配置参数`has-vector-type=true`后,会将向量类型转为 `LONGTEXT` 类型进行写入。 \ No newline at end of file diff --git a/tiflash-upgrade-guide.md b/tiflash-upgrade-guide.md index 5feb21e0c68a..e12989b94d43 100644 --- a/tiflash-upgrade-guide.md +++ b/tiflash-upgrade-guide.md @@ -119,6 +119,10 @@ TiFlash 在 v6.2.0 将数据格式升级到 V3 版本,因此,从 v5.x 或 v6 从 v7.4 开始,为了减少数据整理时产生的读、写放大,PageStorage V3 数据整理时逻辑进行了优化,导致底层部分存储文件名发生改动。因此,升级 TiFlash 到 v7.4 或以上版本后,不支持原地降级到之前的版本。 +## 从 v7.x 升级至 v8.4 或以上版本 + +从 v8.4 开始,为了支持[向量搜索功能](/vector-search-index.md),TiFlash 底层存储格式发生改动。因此,升级 TiFlash 到 v8.4 或以上版本后,不支持原地降级到之前的版本。 + **测试环境及特殊回退需求下的对策** 如果在测试环境下或者其他有特殊回退需求的场景下,可以强制缩容 TiFlash 节点,并重新同步数据。操作步骤详见[缩容 TiFlash 节点](/scale-tidb-using-tiup.md#缩容-tiflash-节点)。 diff --git a/tiflash/tiflash-configuration.md b/tiflash/tiflash-configuration.md index d8138d11bafd..f4e4e624426f 100644 --- a/tiflash/tiflash-configuration.md +++ b/tiflash/tiflash-configuration.md @@ -70,7 +70,9 @@ delta_index_cache_size = 0 ## * format_version = 3 v6.0.0 及 v6.1.x 版本的默认文件格式,具有更完善的检验功能 ## * format_version = 4 v7.3.0 及以前版本的默认文件格式,优化了写放大问题,同时减少了后台线程消耗。 ## * format_version = 5 v7.4.0 及以后版本的默认文件格式(从 v7.3.0 开始引入),该格式可以合并小文件从而减少了物理文件数量。 - # format_version = 5 + ## * format_version = 6 从 v8.4.0 开始引入,部分支持了向量索引的构建与存储。 + ## * format_version = 7 v8.4.0 及以后版本的默认文件格式 (从 v8.4.0 开始引入),该格式用于支持向量索引的构建与存储。 + # format_version = 7 [storage.main] ## 用于存储主要的数据,该目录列表中的数据占总数据的 90% 以上。 diff --git a/vector-search-data-types.md b/vector-search-data-types.md new file mode 100644 index 000000000000..6ec0b8db0e50 --- /dev/null +++ b/vector-search-data-types.md @@ -0,0 +1,248 @@ +--- +title: 向量数据类型 +summary: 本文介绍 TiDB 的向量数据类型。 +--- + +# 向量数据类型 (Vector) + +向量指的是一组浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。针对 AI 应用中大量使用到的嵌入向量 (vector embedding) 数据,TiDB 专门提供了向量数据类型,以便高效地存储和访问这些数据。 + +> **警告:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +目前支持的向量数据类型包括: + +- `VECTOR`: 存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。 +- `VECTOR(D)`: 存储一组单精度浮点数 (Float) 向量,向量维度固定为 `D`。 + +与使用 [`JSON`](/data-type-json.md) 类型相比,使用向量类型具有以下优势: + +- 支持向量索引。可以通过构建[向量搜索索引](/vector-search-index.md)加速查询。 +- 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。 +- 存储格式更优。向量数据类型针对向量数据进行了特别优化,在空间利用和性能效率上都优于 `JSON` 类型。 + +## 语法 + +可以使用以下格式的字符串来表示一个数据类型为向量的值: + +```sql +'[, , ...]' +``` + +示例: + +```sql +CREATE TABLE vector_table ( + id INT PRIMARY KEY, + embedding VECTOR(3) +); + +INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); + +INSERT INTO vector_table VALUES (2, NULL); +``` + +当将不符合语法的字符串作为向量数据插入时,TiDB 会进行报错: + +```sql +[tidb]> INSERT INTO vector_table VALUES (3, '[5, ]'); +ERROR 1105 (HY000): Invalid vector text: [5, ] +``` + +下面的示例中 `embedding` 向量列的维度在建表时已经定义为 `3`,因此当插入其他维度的向量数据时,TiDB 会进行报错: + +```sql +[tidb]> INSERT INTO vector_table VALUES (4, '[0.3, 0.5]'); +ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3) +``` + +可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 + +可参阅[向量搜索索引](/vector-search-index.md)了解向量搜索索引的信息。 + +## 混合存储不同维度的向量 + +省略 `VECTOR` 类型中的维度参数后,就可以在同一列中存储不同维度的向量: + +```sql +CREATE TABLE vector_table ( + id INT PRIMARY KEY, + embedding VECTOR +); + +INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 插入一个 3 维向量 +INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 插入一个 2 维向量 +``` + +需要注意的是,存储了不同维度向量的列不支持构建[向量搜索索引](/vector-search-index.md),因为只有维度相同的向量之间才能计算向量距离。 + +## 比较 + +[比较运算符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符)了解向量数据类型支持的所有函数和操作符。 + +比较向量数据类型时,TiDB 会以向量中的各个元素为单位进行依次比较,如: + +- `[1] < [12]` +- `[1,2,3] < [1,2,5]` +- `[1,2,3] = [1,2,3]` +- `[2,2,3] > [1,2,3]` + +当两个向量的维度不同时,TiDB 采用字典序 (Lexicographical Order) 进行比较,具体规则如下: + +- 两个向量中的各个元素逐一进行数值比较。 +- 当遇到第一个不同的元素时,它们之间的数值比较结果即为两个向量之间的比较结果。 +- 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。例如,`[1,2,3] < [1,2,3,0]`。 +- 长度相同且各个元素相同的两个向量 _相等_ 。 +- 空向量 _小于_ 任何非空向量。例如,`[] < [1]`。 +- 两个空向量 _相等_ 。 + + +在进行向量比较时,请使用[显式转换](#类型转换-cast)将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: + +```sql +-- 因为给出的数据实际上是字符串,因此 TiDB 会按字符串进行比较 +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- 显式转换为向量类型,从而按照向量的比较规则进行正确的比较 +[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); ++--------------------------------------------------+ +| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | ++--------------------------------------------------+ +| 0 | ++--------------------------------------------------+ +1 row in set (0.01 sec) +``` + +## 运算 + +向量数据类型支持算术运算 `+` 和 `-`,对应的是两个向量以元素为单位进行的加法和减法。不支持对不同维度向量进行算术运算,执行这类运算会遇到报错。 + +以下是一些示例: + +```sql +[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]'); ++---------------------------------------------+ +| VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]') | ++---------------------------------------------+ +| [9] | ++---------------------------------------------+ +1 row in set (0.01 sec) + +[tidb]> SELECT VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]'); ++-----------------------------------------------------+ +| VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]') | ++-----------------------------------------------------+ +| [1,1,1] | ++-----------------------------------------------------+ +1 row in set (0.01 sec) + +[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[1,2,3]'); +ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +``` + +## 类型转换 (Cast) + +### 向量与字符串之间的转换 + +可以使用以下函数在向量和字符串之间进行转换: + +- `CAST(... AS VECTOR)`: 将字符串类型转换为向量类型 +- `CAST(... AS CHAR)`: 将向量类型转换为字符串类型 +- `VEC_FROM_TEXT`: 将字符串类型转换为向量类型 +- `VEC_AS_TEXT`: 将向量类型转换为字符串类型 + +出于易用性考虑,如果你使用的函数只支持向量数据类型(例如,向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: + +```sql +-- VEC_DIMS 只接受向量类型,因此你可以直接传入字符串类型,TiDB 会隐式转换为向量类型: +[tidb]> SELECT VEC_DIMS('[0.3, 0.5, -0.1]'); ++------------------------------+ +| VEC_DIMS('[0.3, 0.5, -0.1]') | ++------------------------------+ +| 3 | ++------------------------------+ +1 row in set (0.01 sec) + +-- 也可以使用 VEC_FROM_TEXT 显式地将字符串转换为向量类型后传递给 VEC_DIMS 函数: +[tidb]> SELECT VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')); ++---------------------------------------------+ +| VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')) | ++---------------------------------------------+ +| 3 | ++---------------------------------------------+ +1 row in set (0.01 sec) + +-- 也可以使用 CAST(... AS VECTOR) 进行显式转换: +[tidb]> SELECT VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR)); ++----------------------------------------------+ +| VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR)) | ++----------------------------------------------+ +| 3 | ++----------------------------------------------+ +1 row in set (0.01 sec) +``` + +当你使用的运算符或函数接受多种数据类型时,TiDB 不会进行隐式转换,请先显式地将字符串类型转换为向量类型后,再传递给这些运算符或函数。例如,进行比较运算前,需要显式地将字符串转换为向量类型,否则 TiDB 将会按照字符串类型进行比较,而非按照向量类型进行比较: + +```sql +-- 传入的类型是字符串,因此 TiDB 会按字符串进行比较: +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- 转换为向量类型,以便使用向量类型的比较规则: +[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); ++--------------------------------------------------+ +| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | ++--------------------------------------------------+ +| 0 | ++--------------------------------------------------+ +1 row in set (0.01 sec) +``` + +向量也可以显式地转换为字符串。以使用 `VEC_AS_TEXT()` 函数为例: + +```sql +-- 字符串首先被隐式地转换成向量,然后被显式地转为字符串,因而返回了一个规范化的字符串格式: +[tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); ++--------------------------------------+ +| VEC_AS_TEXT('[0.3, 0.5, -0.1]') | ++--------------------------------------+ +| [0.3,0.5,-0.1] | ++--------------------------------------+ +1 row in set (0.01 sec) +``` + +如需了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 + +### 向量与其他数据类型之间的转换 + +目前 TiDB 无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以使用字符串作为中间类型进行转换。 + +## 使用限制 + +- 向量最大支持 16383 维。 +- 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 目前,向量类型不能存储双精度浮点数。计划在未来的版本中支持这一功能。在此期间,如果为向量类型导入双精度浮点数,它们将被转换为单精度数。 + +有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 + +## MySQL 兼容性 + +向量数据类型只在 TiDB 中支持,MySQL 不支持。 + +## 另请参阅 + +- [向量函数和操作符](/vector-search-functions-and-operators.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md new file mode 100644 index 000000000000..3add099d89e8 --- /dev/null +++ b/vector-search-functions-and-operators.md @@ -0,0 +1,284 @@ +--- +title: 向量函数和操作符 +summary: 本文介绍 TiDB 的向量相关函数和操作。 +--- + +# 向量函数和操作符 + +本文介绍 TiDB 支持的向量函数和操作符。 + +> **警告:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 向量函数 + +TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量函数: + +**向量距离函数** + +| 函数名 | 描述 | +| --------------------------------------------------------- | ----------------------------------------------------------- | +| [VEC_L2_DISTANCE](#vec_l2_distance) | 计算两个向量之间的 L2 距离 (欧氏距离) | +| [VEC_COSINE_DISTANCE](#vec_cosine_distance) | 计算两个向量之间的余弦距离 | +| [VEC_NEGATIVE_INNER_PRODUCT](#vec_negative_inner_product) | 计算两个向量内积的负数 | +| [VEC_L1_DISTANCE](#vec_l1_distance) | 计算两个向量之间的 L1 距离 (曼哈顿距离) | + +**其他向量函数** + +| 函数名 | Description | +| ------------------------------- | --------------------------------------------------- | +| [VEC_DIMS](#vec_dims) | 计算向量的维度 | +| [VEC_L2_NORM](#vec_l2_norm) | 计算向量的 L2 范数 (欧氏规范) | +| [VEC_FROM_TEXT](#vec_from_text) | 将字符串类型转换为向量类型 | +| [VEC_AS_TEXT](#vec_as_text) | 将向量类型转换为字符串类型 | + +## 扩展的内置函数和运算符 + +TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了[向量数据类型](/vector-search-data-types.md)。 + +**算术运算符** + +| 运算符 | 描述 | +| :-------------------------------------------------------------------------------------- | :--------------------------------------- | +| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | 向量以元素为单位进行加法运算符 | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 向量以元素为单位进行减法运算符 | + +关于向量运算工作原理的更多信息,请参阅[向量数据类型的运算](/vector-search-data-types.md#运算)。 + +**聚合函数 (GROUP BY)** + +| 函数名 | 描述 | +| :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | +| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | 返回行数 | +| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | 返回不同值的行数 | +| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | 返回最大值 | +| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | 返回最小值 | + +**比较函数与操作符** + +| 名称 | 描述 | +| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | 检查值是否在某个取值范围内 | +| [`COALESCE()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | 获得第一个非 `NULL` 参数 | +| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | 相等比较符 | +| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | 安全的 `NULL` 相等比较符 | +| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | 大于运算符 | +| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | 大于或等于运算符 | +| [`GREATEST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | 返回最大参数 | +| [`IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | 检查值是否在一组数值之内 | +| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | 判断是否为 `NULL` 值 | +| [`ISNULL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | 判断参数是否为 `NULL` | +| [`LEAST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | 返回最小参数 | +| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | 小于运算符 | +| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | 小于或等于运算符 | +| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | 检查值是否不在某个取值范围内 | +| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | 不等运算符 | +| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | 检查值是否不在一组数值之内 | + +关于如何比较向量的更多信息,请参阅[向量数据类型的比较](/vector-search-data-types.md#比较)。 + +**控制流程函数** + +| 函数名 | 描述 | +| :------------------------------------------------------------------------------------------------ | :--------------------------- | +| [`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | Case 操作符 | +| [`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) | 构建 If/else | +| [`IFNULL()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | 构建 Null if/else | +| [`NULLIF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) | 如果 expr1 = expr2,返回 `NULL` | + +**转换函数** + +| 函数名 | 描述 | +| :------------------------------------------------------------------------------------------ | :----------------------------- | +| [`CAST()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) | 将值转换为字符串或向量类型 | +| [`CONVERT()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | 将值转换为字符串类型 | + +关于如何使用 `CAST()` 的更多信息,请参阅[向量数据类型的转换](/vector-search-data-types.md#类型转换-cast)。 + +## 使用示例 + +### VEC_L2_DISTANCE + +```sql +VEC_L2_DISTANCE(vector1, vector2) +``` + +计算两个向量之间的 [L2 距离](https://zh.wikipedia.org/wiki/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E8%B7%9D%E7%A6%BB) (欧式距离),使用的公式为: + +$DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ + +参与计算的两个向量的维度必须相同。当两个向量的维度不同时,TiDB 将返回错误信息。 + +示例: + +```sql +[tidb]> SELECT VEC_L2_DISTANCE('[0,3]', '[4,0]'); ++-----------------------------------+ +| VEC_L2_DISTANCE('[0,3]', '[4,0]') | ++-----------------------------------+ +| 5 | ++-----------------------------------+ +``` + +### VEC_COSINE_DISTANCE + +```sql +VEC_COSINE_DISTANCE(vector1, vector2) +``` + +计算两个向量之间的[余弦 (cosine)](https://zh.wikipedia.org/wiki/%E4%BD%99%E5%BC%A6%E7%9B%B8%E4%BC%BC%E6%80%A7) 距离,使用的公式为: + +$DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}}\cdot {\sqrt {\sum \limits _{i=1}^{n}{q_{i}^{2}}}}}}$ + +参与计算的两个向量的维度必须相同。当两个向量的维度不同时,TiDB 将返回错误信息。 + +示例: + +```sql +[tidb]> SELECT VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]'); ++-------------------------------------------+ +| VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]') | ++-------------------------------------------+ +| 2 | ++-------------------------------------------+ +``` + +### VEC_NEGATIVE_INNER_PRODUCT + +```sql +VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2) +``` + +计算两个向量之间[内积](https://zh.wikipedia.org/wiki/%E7%82%B9%E7%A7%AF)的负值,使用的公式为: + +$DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ + +参与计算的两个向量的维度必须相同。当两个向量的维度不同时,TiDB 将返回错误信息。 + +示例: + +```sql +[tidb]> SELECT VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]'); ++----------------------------------------------+ +| VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]') | ++----------------------------------------------+ +| -11 | ++----------------------------------------------+ +``` + +### VEC_L1_DISTANCE + +```sql +VEC_L1_DISTANCE(vector1, vector2) +``` + +计算两个向量之间的 [L1 距离](https://zh.wikipedia.org/wiki/%E6%9B%BC%E5%93%88%E9%A0%93%E8%B7%9D%E9%9B%A2) (曼哈顿距离),使用的公式为: + +$DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ + +参与计算的两个向量的维度必须相同。当两个向量的维度不同时,TiDB 将返回错误信息。 + +示例: + +```sql +[tidb]> SELECT VEC_L1_DISTANCE('[0,0]', '[3,4]'); ++-----------------------------------+ +| VEC_L1_DISTANCE('[0,0]', '[3,4]') | ++-----------------------------------+ +| 7 | ++-----------------------------------+ +``` + +### VEC_DIMS + +```sql +VEC_DIMS(vector) +``` + +返回向量的维度。 + +示例: + +```sql +[tidb]> SELECT VEC_DIMS('[1,2,3]'); ++---------------------+ +| VEC_DIMS('[1,2,3]') | ++---------------------+ +| 3 | ++---------------------+ + +[tidb]> SELECT VEC_DIMS('[]'); ++----------------+ +| VEC_DIMS('[]') | ++----------------+ +| 0 | ++----------------+ +``` + +### VEC_L2_NORM + +```sql +VEC_L2_NORM(vector) +``` + +计算向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0)(欧几里得范数),使用的公式为: + +$NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ + +示例: + +```sql +[tidb]> SELECT VEC_L2_NORM('[3,4]'); ++----------------------+ +| VEC_L2_NORM('[3,4]') | ++----------------------+ +| 5 | ++----------------------+ +``` + +### VEC_FROM_TEXT + +```sql +VEC_FROM_TEXT(string) +``` + +将字符串类型转换为向量类型。 + +示例: + +```sql +[tidb]> SELECT VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]'); ++-------------------------------------------------+ +| VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]') | ++-------------------------------------------------+ +| [4,6] | ++-------------------------------------------------+ +``` + +### VEC_AS_TEXT + +```sql +VEC_AS_TEXT(vector) +``` + +将向量类型转换为字符串类型。 + +示例: + +```sql +[tidb]> SELECT VEC_AS_TEXT('[1.000, 2.5]'); ++-------------------------------+ +| VEC_AS_TEXT('[1.000, 2.5]') | ++-------------------------------+ +| [1,2.5] | ++-------------------------------+ +``` + +## MySQL 兼容性 + +向量函数、有关向量的内置函数和向量数据类型运算符只在 TiDB 中支持,MySQL 不支持。 + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md new file mode 100644 index 000000000000..cabeebf12d68 --- /dev/null +++ b/vector-search-get-started-using-python.md @@ -0,0 +1,232 @@ +--- +title: 使用 Python 开始向量搜索 +summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语义搜索的人工智能应用程序。 +--- + +# 使用 Python 开始向量搜索 + +本文将展示如何开发一个简单的 AI 应用,这个 AI 应用实现了简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以智能地理解你的输入,返回更相关的结果。例如,在“狗”、“鱼”和“树”这三条内容中搜索“一种会游泳的动物”时,语义搜索会将“鱼”作为最相关的结果返回。 + +在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型完成这个 AI 应用的开发。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 快速开始 + +以下为从零开始构建这个应用的详细步骤,你也可以从 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 开源代码库获取到完整代码,直接运行示例。 + +### 第 1 步:新建一个 Python 项目 + +在你的本地目录中,新建一个 Python 项目和一个名为 `example.py` 的文件: + +```shell +mkdir python-client-quickstart +cd python-client-quickstart +touch example.py +``` + +### 第 2 步:安装所需的依赖 + +在该项目的目录下,运行以下命令安装所需的软件包: + +```shell +pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv +``` + +- `tidb-vector`:用于与 TiDB 向量搜索交互的 Python 客户端。 +- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成[向量嵌入](/vector-search-overview.md#向量嵌入)。 + +### 第 3 步:配置 TiDB 集群的连接字符串 + +根据不同的 TiDB 集群部署方式,配置集群的连接字符串。 + + + +
+ +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: + +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如:TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +``` + +如果你在本机运行 TiDB,`HOST` 默认为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:TiDB 集群的主机号。 +- ``:TiDB 集群的端口。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `SQLAlchemy`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + +4. 单击 **PyMySQL** 选项卡,复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下新建一个 `.env` 文件,将连接字符串粘贴到其中。 + + 以下为 MacOS 的示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +
+ +
+ +### 第 4 步:初始化嵌入模型 + +[嵌入模型](/vector-search-overview.md#嵌入模型)用于将数据转换为[向量嵌入](/vector-search-overview.md#向量嵌入)。本示例将使用预训练模型 [**msmarco-MiniLM-L12-cos-v5**](https://huggingface.co/sentence-transformers/msmarco-MiniLM-L12-cos-v5) 将文本数据转换为向量嵌入。该模型为一个轻量级模型,由 `sentence-transformers` 库提供,可将文本数据转换为 384 维的向量嵌入。 + +将以下代码复制到 `example.py` 文件中,完成模型的设置。这段代码初始化了一个 `SentenceTransformer` 实例,并定义了一个 `text_too_embedding()` 函数用于将文本数据转换为向量数据。 + +```python +from sentence_transformers import SentenceTransformer + +print("Downloading and loading the embedding model...") +embed_model = SentenceTransformer("sentence-transformers/msmarco-MiniLM-L12-cos-v5", trust_remote_code=True) +embed_model_dims = embed_model.get_sentence_embedding_dimension() + +def text_to_embedding(text): + """Generates vector embeddings for the given text.""" + embedding = embed_model.encode(text) + return embedding.tolist() +``` + +### 第 5 步:连接到 TiDB 集群 + +使用 `TiDBVectorClient` 类连接到 TiDB 集群,并创建一个包含向量列的表 `embedded_documents`。 + +> **Note** +> +> 请确保你创建的表中向量列的维度与嵌入模型生成的向量维度一致。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度, `embedded_documents` 的向量列维度也应为 384。 + +```python +import os +from tidb_vector.integrations import TiDBVectorClient +from dotenv import load_dotenv + +# 从 .env 文件加载连接配置信息 +load_dotenv() + +vector_store = TiDBVectorClient( + # embedded_documents 表将用于存储向量数据 + table_name='embedded_documents', + # 指定 TiDB 集群的连接字符串 + connection_string=os.environ.get('TIDB_DATABASE_URL'), + # 指定嵌入模型生成的向量的维度 + vector_dimension=embed_model_dims, + # 如果表已经存在,则重新创建该表 + drop_existing_table=True, +) +``` + +### 第 6 步:将文本数据转换为向量嵌入,并向表中插入数据 + +准备一些文本数据,比如 `"dog"`、`"fish"` 和 `"tree"`。以下代码将使用 `text_to_embedding()` 函数将这些文本数据转换为向量嵌入,然后将向量嵌入插入到 `embedded_documents` 表中: + +```python +documents = [ + { + "id": "f8e7dee2-63b6-42f1-8b60-2d46710c1971", + "text": "dog", + "embedding": text_to_embedding("dog"), + "metadata": {"category": "animal"}, + }, + { + "id": "8dde1fbc-2522-4ca2-aedf-5dcb2966d1c6", + "text": "fish", + "embedding": text_to_embedding("fish"), + "metadata": {"category": "animal"}, + }, + { + "id": "e4991349-d00b-485c-a481-f61695f2b5ae", + "text": "tree", + "embedding": text_to_embedding("tree"), + "metadata": {"category": "plant"}, + }, +] + +vector_store.insert( + ids=[doc["id"] for doc in documents], + texts=[doc["text"] for doc in documents], + embeddings=[doc["embedding"] for doc in documents], + metadatas=[doc["metadata"] for doc in documents], +) +``` + +### 第 7 步:执行语义搜索 + +查询一个与 `documents` 中的任何单词都不匹配的关键词,比如 "a swimming animal"。 + +以下的代码会再次使用 `text_to_embedding()` 函数将查询文本转换为向量嵌入,然后使用该嵌入进行查询,找出最匹配的前三个词。 + +```python +def print_result(query, result): + print(f"Search result (\"{query}\"):") + for r in result: + print(f"- text: \"{r.document}\", distance: {r.distance}") + +query = "a swimming animal" +query_embedding = text_to_embedding(query) +search_result = vector_store.query(query_embedding, k=3) +print_result(query, search_result) +``` + +运行 `example.py` 文件,输出结果如下: + +```plain +Search result ("a swimming animal"): +- text: "fish", distance: 0.4562914811223072 +- text: "dog", distance: 0.6469335836410557 +- text: "tree", distance: 0.798545178640937 +``` + +搜索结果中的 3 个词会按向量的远近排列:距离越小,对应的 `document` 越相关。 + +因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 + +## 另请参阅 + +- [Vector Data Types](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md new file mode 100644 index 000000000000..fe2010885e84 --- /dev/null +++ b/vector-search-get-started-using-sql.md @@ -0,0 +1,178 @@ +--- +title: 使用 SQL 开始向量搜索 +summary: 了解如何在 TiDB 中使用 SQL 语句快速开始向量搜索,从而为你的生成式 AI 应用提供支持。 +--- + +# 使用 SQL 开始向量搜索 + +TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md),并引入了[向量数据类型](/vector-search-data-types.md)和多个[向量函数](/vector-search-functions-and-operators.md)。 + +本文将展示如何使用 SQL 语句在 TiDB 中进行向量搜索。在本文中,你将使用 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)完成以下任务: + +- 连接到 TiDB 集群 +- 创建向量表 +- 存储向量嵌入 +- 执行向量搜索查询 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 快速开始 + +### 第 1 步:连接到 TiDB 集群 + +根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 + + + +
+ +在本地部署的集群启动后,在终端中执行你的集群连接命令: + +以下为 MacOS 上的连接命令示例: + +```bash + mysql --comments --host 127.0.0.1 --port 4000 -u root +``` + +
+ +
+ +对于 TiDB Cloud Serverless 集群,可以按照以下步骤连接到集群: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 在连接对话框中,选择 **Connect With** 下拉列表中的 **MySQL CLI**,并保留 **Connection Type** 的默认值为 **Public**。 + +4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 复制对话框中的连接命令,并粘贴到终端中执行。以下为 macOS 上的连接命令示例: + + ```bash + mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' + ``` + +
+ +
+ +### 第 2 步:创建向量表 + +在建表时,你可以使用 `VECTOR` 数据类型声明指定列为[向量](/vector-search-overview.md#向量嵌入)列。 + +例如,如需创建一张带有三维 `VECTOR` 列的 `embedded_documents` 表,可以在 MySQL CLI 中执行以下 SQL 语句: + +```sql +USE test; +CREATE TABLE embedded_documents ( + id INT PRIMARY KEY, + -- document 列存储 document 的原始内容 + document TEXT, + -- embedding 列存储 document 的向量表示 + embedding VECTOR(3) +); +``` + +预期输出如下: + +```text +Query OK, 0 rows affected (0.27 sec) +``` + +### 第 3 步:向表中插入向量 + +向 `embedded_documents` 表中插入三行,每一行包含数据和数据的[向量嵌入](/vector-search-overview.md#向量嵌入): + +```sql +INSERT INTO embedded_documents +VALUES + (1, 'dog', '[1,2,1]'), + (2, 'fish', '[1,2,4]'), + (3, 'tree', '[1,0,0]'); +``` + +预期输出如下: + +``` +Query OK, 3 rows affected (0.15 sec) +Records: 3 Duplicates: 0 Warnings: 0 +``` + +> **Note** +> +> 为了方便展示,本示例简化了向量的维数,仅使用三维向量。 +> +> 在实际应用中,[嵌入模型](/vector-search-overview.md#嵌入模型)通常会生成数百或数千维的向量。 + +### 第 4 步:查询向量表 + +要验证上一步中的三行数据是否已正确插入,可以查询 `embedded_documents` 表: + +```sql +SELECT * FROM embedded_documents; +``` + +预期输出如下: + +```sql ++----+----------+-----------+ +| id | document | embedding | ++----+----------+-----------+ +| 1 | dog | [1,2,1] | +| 2 | fish | [1,2,4] | +| 3 | tree | [1,0,0] | ++----+----------+-----------+ +3 rows in set (0.15 sec) +``` + +### 第 5 步:执行向量搜索查询 + +与全文搜索类似,在使用向量搜索时,你需要指定搜索词。 + +在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用[嵌入模型](/vector-search-overview.md#嵌入模型)将用户的搜索词转换为向量。 + +执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量(余弦距离最小)的前三个向量。 + +```sql +SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance +FROM embedded_documents +ORDER BY distance +LIMIT 3; +``` + +预期输出如下: + +```plain ++----+----------+---------------------+ +| id | document | distance | ++----+----------+---------------------+ +| 2 | fish | 0.00853986601633272 | +| 1 | dog | 0.12712843905603044 | +| 3 | tree | 0.7327387580875756 | ++----+----------+---------------------+ +3 rows in set (0.15 sec) +``` + +搜索结果中的 3 个词会按向量的距离排列:距离越小,对应的 `document` 越相关。 + +因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md new file mode 100644 index 000000000000..7c446085cb6d --- /dev/null +++ b/vector-search-improve-performance.md @@ -0,0 +1,40 @@ +--- +title: 优化向量搜索性能 +summary: 了解优化 TiDB 向量搜索性能的最佳实践。 +--- + +# 优化向量搜索性能 + +在 TiDB 中,你可以通过向量搜索功能进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索,查找与给定的图像、文档等相似的结果。为了提升查询性能,请参考以下最佳实践。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 为向量列添加向量搜索索引 + +[向量搜索索引](/vector-search-index.md)可显著提高向量搜索查询的性能,通常能提高 10 倍或更多,而召回率仅略有下降。 + +## 确保向量索引已完全构建 + +向量搜索索引是通过异步方式构建的。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#view-index-build-progress)。 + +## 减少向量维数或缩短嵌入时间 + +随着向量维度大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 + +为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,你需要评估改变嵌入模型对向量查询准确性的影响。 + +一些嵌入模型,如 OpenAI `text-embedding-3-large`,支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失向量表示的概念特征的情况下,从向量序列末尾移除一些数字。你也可以使用这种嵌入模型来减少向量维数。 + +## 在结果输出中排除向量列 + +向量嵌入数据通常很大,而且只在搜索过程中使用。通过从查询结果中排除向量列,可以显著减少 TiDB 服务器和 SQL 客户端之间传输的数据量,从而提高查询性能。 + +要从结果输出中排除向量列,请在 `SELECT` 语句中明确指定需要检索的列,而不是使用 `SELECT *` 检索所有列。 + +## 预热索引 + +当访问一个从未被使用过或长时间未被使用过的索引(冷访问)时,TiDB 需要从 S3 或磁盘(而不是内存)加载整个索引。这个过程需要一定的时间,往往会导致较高的查询延迟。此外,如果集群长时间(比如数小时)内没有进行 SQL 查询,计算资源就会被回收,这样下次访问时就会变成冷访问。 + +要避免这种查询延迟,可在实际工作负载前,使用类似的向量搜索查询对索引进行预热。 \ No newline at end of file diff --git a/vector-search-index.md b/vector-search-index.md new file mode 100644 index 000000000000..83e271adb7e5 --- /dev/null +++ b/vector-search-index.md @@ -0,0 +1,286 @@ +--- +title: 向量搜索索引 +summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (K-Nearest Neighbors, KNN) 查询。 +--- + +# 向量搜索索引 + +K 近邻(K-Nearest Neighbors,简称 KNN)搜索是一种在向量空间中找到距离给定向量最近的 K 个向量的查询。实现 K 近邻搜索最直接的方法是暴力搜索(即计算向量空间中所有点与给定向量之间的距离),这种方法可以达到最高的精确度,但在实际应用中其搜索速度往往过于缓慢。因此,K 近邻搜索通常会采用近似算法来提高搜索效率。 + +在 TiDB 中,你可以创建并利用向量搜索索引来对[向量数据类型](/vector-search-data-types.md)的列进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索。通过使用向量搜索索引,整个查询可在几毫秒内完成。 + +> **警告:** +> +> 向量搜索索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 向量搜索索引算法。 + +## 使用限制 + +- 集群需要提前部署 TiFlash 节点。 +- 向量搜索索引不能作为主键或者唯一索引。 +- 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 +- 创建和使用搜索向量索引时需要指定距离函数。目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`。 +- 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 +- 不支持删除具有向量搜索索引的列,也不支持在同一个 SQL 语句中创建多个索引。 +- 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 +- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 + +## 创建 HNSW 向量搜索索引 + +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是当前最流行的向量搜索索引算法之一。它性能良好,而且准确率相对较高,特定情况下可达 98%。 + +在 TiDB 中,你可以通过以下任一种方式为[向量数据类型](/vector-search-data-types.md)的列创建 HNSW 索引。 + +- 在建表时,使用以下语法来指定为哪一个向量列创建 HNSW 索引: + + ```sql + CREATE TABLE foo ( + id INT PRIMARY KEY, + data VECTOR(5), + VECTOR INDEX idx_data USING HNSW ((VEC_COSINE_DISTANCE(data))) + ); + ``` + +- 对于现有的表,如果该表已包含向量列,可以通过以下语法为向量列创建 HNSW 索引: + + ```sql + CREATE VECTOR INDEX idx_name ON foo ((VEC_COSINE_DISTANCE(data))) USING HNSW; + + ALTER TABLE foo ADD VECTOR INDEX idx_name ((VEC_COSINE_DISTANCE(data))) USING HNSW; + ``` + +> **注意:** +> +> 向量搜索索引目前为实验特性,其语法可能会在 GA 前发生变化。 + +在创建 HNSW 向量索引时,你需要指定向量的距离函数: + +- 余弦距离:`((VEC_COSINE_DISTANCE(cols_name))) USING HNSW` +- L2 距离:`((VEC_L2_DISTANCE(cols_name))) USING HNSW` + +你只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引,不能为混合维度的向量列 (如 `VECTOR` ) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 + +有关向量搜索索引的约束和限制,请参阅[向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束)。 + +## 使用向量搜索索引 + +在 K 近邻搜索查询中,可以通过 `ORDER BY ... LIMIT` 子句来使用向量搜索索引,如下所示: + +```sql +SELECT * +FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +LIMIT 10 +``` + +要在向量搜索中使用索引,请确保 `ORDER BY ... LIMIT` 子句中使用的距离函数与创建向量索引时指定的距离函数相同。 + +## 使用带过滤条件的向量搜索索引 + +包含预过滤条件(使用 `WHERE` 子句)的查询无法使用向量搜索索引,因为这样的查询并没有严格按照 SQL 语义来查询 K 近邻。例如: + +```sql +-- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: + +SELECT * FROM vec_table +WHERE category = "document" +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +如需使用带过滤条件的向量搜索索引,可以采用以下几种方法: + +**向量搜索后再过滤:** 先查询 K 个最近的邻居,再过滤掉不需要的结果: + +```sql +-- 对于以下查询,过滤条件是在 KNN 之后执行的,因此可以使用向量索引: + +SELECT * FROM +( + SELECT * FROM vec_table + ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') + LIMIT 5 +) t +WHERE category = "document"; + +-- 请注意,如果过滤掉一些结果,此查询返回的结果可能少于 5 个。 +``` + +**对表进行分区:**在[分区表](/partitioned-table.md)内的查询可以充分利用向量索引。如果你需要进行等值过滤,会非常有用,因为等值过滤可以转化为访问指定的分区。 + +例如,假设你需要查找与特定产品版本最接近的文档: + +```sql +-- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: +SELECT * FROM docs +WHERE ver = "v2.0" +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +如需使用向量搜索索引,你可以先对表进行分区,然后使用 [`PARTITION` 关键字](/partitioned-table.md#partition-selection) 在特定分区内进行查询,而不是使用 `WHERE` 子句。 + +```sql +CREATE TABLE docs ( + id INT, + ver VARCHAR(10), + doc TEXT, + embedding VECTOR(3), + VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding))) +) PARTITION BY LIST COLUMNS (ver) ( + PARTITION p_v1_0 VALUES IN ('v1.0'), + PARTITION p_v1_1 VALUES IN ('v1.1'), + PARTITION p_v1_2 VALUES IN ('v1.2'), + PARTITION p_v2_0 VALUES IN ('v2.0') +); + +SELECT * FROM docs +PARTITION (p_v2_0) +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +更多信息,请参阅[分区表](/partitioned-table.md)。 + +## 查看索引构建进度 + +与其他索引不同,向量搜索索引是通过异步方式构建的。这意味着,在完成大批量数据插入后,向量索引可能不会立即构建完成以供查询使用,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 + +要查看索引构建进度,可以按如下方式查询 `INFORMATION_SCHEMA.TIFLASH_INDEXES` 表: + +```sql +SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; ++---------------+------------+----------------+----------+--------------------+-------------+-----------+------------+---------------------+-------------------------+--------------------+------------------------+------------------+ +| TIDB_DATABASE | TIDB_TABLE | TIDB_PARTITION | TABLE_ID | BELONGING_TABLE_ID | COLUMN_NAME | COLUMN_ID | INDEX_KIND | ROWS_STABLE_INDEXED | ROWS_STABLE_NOT_INDEXED | ROWS_DELTA_INDEXED | ROWS_DELTA_NOT_INDEXED | TIFLASH_INSTANCE | ++---------------+------------+----------------+----------+--------------------+-------------+-----------+------------+---------------------+-------------------------+--------------------+------------------------+------------------+ +| test | sample | NULL | 106 | -1 | vec | 2 | HNSW | 0 | 13000 | 0 | 2000 | store-6ba728d2 | +| test | sample | NULL | 106 | -1 | vec | 2 | HNSW | 10500 | 0 | 0 | 4500 | store-7000164f | ++---------------+------------+----------------+----------+--------------------+-------------+-----------+------------+---------------------+-------------------------+--------------------+------------------------+------------------+ +``` + +- 可以通过 `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列查看索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,表示索引构建完成。 + + 作为参考,对于一个 500 MiB 的向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 + +- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到稳定层。这个合并过程称为“压缩”。 + + Delta 层本身是不包含索引的。为了达到最佳性能,你可以强制将 Delta 层合并到稳定层,以确保所有的数据都能够被索引: + + ```sql + ALTER TABLE COMPACT; + ``` + + 更多信息,请参阅 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md)。 + +此外,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 DDL 任务的执行进度,观察其 `row count`。不过这种方式并不准确,`row count` 的值是从 `TIFLASH_INDEXES` 里的 `rows_stable_indexed` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 + +## 查看是否使用了向量搜索索引 + +你可以使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 或 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句查看一个查询是否使用了向量搜索索引。如果 `TableFullScan` 执行计划的 `operator info` 列中出现了 `annIndex:`,表示 TiDB 在扫描该表时使用了向量搜索索引。 + +**示例:使用了向量索引的查询** + +```sql +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +LIMIT 10; ++-----+-------------------------------------------------------------------------------------+ +| ... | operator info | ++-----+-------------------------------------------------------------------------------------+ +| ... | ... | +| ... | Column#5, offset:0, count:10 | +| ... | ..., vec_cosine_distance(test.vector_table_with_index.embedding, [1,2,3])->Column#5 | +| ... | MppVersion: 1, data:ExchangeSender_16 | +| ... | ExchangeType: PassThrough | +| ... | ... | +| ... | Column#4, offset:0, count:10 | +| ... | ..., vec_cosine_distance(test.vector_table_with_index.embedding, [1,2,3])->Column#4 | +| ... | annIndex:COSINE(test.vector_table_with_index.embedding..[1,2,3], limit:10), ... | ++-----+-------------------------------------------------------------------------------------+ +9 rows in set (0.01 sec) +``` + +**示例:由于未指定 Top K,导致未使用向量搜索索引的查询** + +```sql +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index + -> ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]'); ++--------------------------------+-----+--------------------------------------------------+ +| id | ... | operator info | ++--------------------------------+-----+--------------------------------------------------+ +| Projection_15 | ... | ... | +| └─Sort_4 | ... | Column#4 | +| └─Projection_16 | ... | ..., vec_cosine_distance(..., [1,2,3])->Column#4 | +| └─TableReader_14 | ... | MppVersion: 1, data:ExchangeSender_13 | +| └─ExchangeSender_13 | ... | ExchangeType: PassThrough | +| └─TableFullScan_12 | ... | keep order:false, stats:pseudo | ++--------------------------------+-----+--------------------------------------------------+ +6 rows in set, 1 warning (0.01 sec) +``` + +在某些情况下,如果无法使用向量搜索索引,TiDB 会生成警告信息,以帮助你了解背后的原因: + +```sql +-- 使用了错误的距离函数: +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY Vec_l2_Distance(embedding, '[1, 2, 3]') +LIMIT 10; + +[tidb]> SHOW WARNINGS; +ANN index not used: not ordering by COSINE distance + +-- 使用了错误的排序方式: +[tidb]> EXPLAIN SELECT * FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') DESC +LIMIT 10; + +[tidb]> SHOW WARNINGS; +ANN index not used: index can be used only when ordering by vec_cosine_distance() in ASC order +``` + +## 分析向量搜索性能 + +你可以执行 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句,然后查看输出中的 `execution info` 列了解向量索引使用情况的详细信息: + +```sql +[tidb]> EXPLAIN ANALYZE SELECT * FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +LIMIT 10; ++-----+--------------------------------------------------------+-----+ +| | execution info | | ++-----+--------------------------------------------------------+-----+ +| ... | time:339.1ms, loops:2, RU:0.000000, Concurrency:OFF | ... | +| ... | time:339ms, loops:2 | ... | +| ... | time:339ms, loops:3, Concurrency:OFF | ... | +| ... | time:339ms, loops:3, cop_task: {...} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{time:327.5ms, loops:1, threads:4} | ... | +| ... | tiflash_task:{...}, vector_idx:{ | ... | +| | load:{total:68ms,from_s3:1,from_disk:0,from_cache:0},| | +| | search:{total:0ms,visited_nodes:2,discarded_nodes:0},| | +| | read:{vec_total:0ms,others_total:0ms}},...} | | ++-----+--------------------------------------------------------+-----+ +``` + +> **注意:** +> +> 执行信息为 TiDB 内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 + +以下为一些重要字段的解释: + +- `vector_index.load.total`:加载索引的总时长。该字段的值可能会超过查询实际耗时,因为 TiDB 可能会并行加载多个向量索引。 +- `vector_index.load.from_s3`:从 S3 加载的索引数量。 +- `vector_index.load.from_disk`:从磁盘加载的索引数量。这些索引之前已经从 S3 下载到磁盘上。 +- `vector_index.load.from_cache`:从缓存中加载的索引数量。这些索引之前已经从 S3 下载并存储在缓存中。 +- `vector_index.search.total`:在索引中搜索的总时长。如果该时间存在较大的延迟,通常意味着该索引为冷索引(以前从未被访问过,或很久以前被访问过),因此在索引中搜索时会产生较多的 I/O 操作。该字段的值可能会超过查询实际耗时,因为 TiDB 可能会并行搜索多个向量索引。 +- `vector_index.search.discarded_nodes`:在搜索过程中已访问但被丢弃的向量行数。这些被丢弃的行不会包含在搜索结果中。如果该字段的值较大,通常表示表中有很多由于 `UPDATE` 或 `DELETE` 操作导致的数据过时的行。 + +关于执行信息输出的更多信息,请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及[使用 `EXPLAIN` 解读执行计划](/explain-walkthrough.md)。 + +## 另请参阅 + +- [优化向量搜索性能](/vector-search-improve-performance.md) +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md new file mode 100644 index 000000000000..8d9f54e41a02 --- /dev/null +++ b/vector-search-integrate-with-django-orm.md @@ -0,0 +1,262 @@ +--- +title: 在 Django ORM 中使用 TiDB 向量搜索 +summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 +--- + +# 在 Django ORM 中使用 TiDB 向量搜索 + +本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 运行示例应用程序 + +你可以通过以下步骤快速了解如何在 Django ORM 中使用 TiDB 向量搜索。 + +### 第 1 步:克隆示例代码仓库 + +将 `tidb-vector-python` 仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 第 2 步:创建虚拟环境 + +为你的项目创建虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-django-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 第 3 步:安装所需的依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +你也可以直接为项目安装以下依赖项: + +```bash +pip install Django django-tidb mysqlclient numpy python-dotenv +``` + +如果遇到 mysqlclient 安装问题,请参阅 mysqlclient 官方文档。 + +#### 什么是 `django-tidb`? + +`django-tidb` 是一个为 Django 提供的 TiDB 适配器。通过该适配器,Django ORM 实现了对 TiDB 特有的功能(如,向量搜索)的支持,并解决了 TiDB 和 Django 之间的兼容性问题。 + +安装 `django-tidb` 时,请选择与你的 Django 版本相匹配的版本。例如,如果你使用的是 `django==4.2.*`, 则应安装 `django-tidb===4.2.*`,其中 minor 版本号不需要完全相同。建议使用最新的 minor 版本。 + +更多信息,请参考 [django-tidb 仓库](https://github.com/pingcap/django-tidb)。 + +### 第 4 步:配置环境变量 + +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: + +```dotenv +TIDB_HOST=127.0.0.1 +TIDB_PORT=4000 +TIDB_USERNAME=root +TIDB_PASSWORD= +TIDB_DATABASE=test +``` + +如果你在本机运行 TiDB,`TIDB_HOST` 默认为 `127.0.0.1`。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- `TIDB_HOST`:TiDB 集群的主机号。 +- `TIDB_PORT`:TiDB 集群的端口号。 +- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 +- `TIDB_DATABASE`:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `General`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + +4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 + + - `TIDB_HOST`:TiDB 集群的主机号。 + - `TIDB_PORT`:TiDB 集群的端口号。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 + + 以下为 MacOS 的示例: + + ```dotenv + TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_PORT=4000 + TIDB_USERNAME=********.root + TIDB_PASSWORD=******** + TIDB_DATABASE=test + TIDB_CA_PATH=/etc/ssl/cert.pem + ``` + +
+ +
+ +### 第 5 步:运行示例应用程序 + +迁移数据库模式: + +```bash +python manage.py migrate +``` + +运行 Django 开发服务器: + +```bash +python manage.py runserver +``` + +打开浏览器,访问 `http://127.0.0.1:8000` 查看该示例程序的可视化界面。以下为该程序可用的 API 路径: + +| API 路径 | 描述 | +| --------------------------------------- | ---------------------------------------- | +| `POST: /insert_documents` | 插入含有向量的 `document`。 | +| `GET: /get_nearest_neighbors_documents` | 获取距离最近的 3 个 `document`。 | +| `GET: /get_documents_within_distance` | 获取处于给定距离内的所有 `document`。 | + +## 示例代码片段 + +你可以参考以下示例代码片段来完成自己的应用程序开发。 + +### 连接到 TiDB 集群 + +打开 `sample_project/settings.py` 文件,添加以下配置: + +```python +dotenv.load_dotenv() + +DATABASES = { + "default": { + # https://github.com/pingcap/django-tidb + "ENGINE": "django_tidb", + "HOST": os.environ.get("TIDB_HOST", "127.0.0.1"), + "PORT": int(os.environ.get("TIDB_PORT", 4000)), + "USER": os.environ.get("TIDB_USERNAME", "root"), + "PASSWORD": os.environ.get("TIDB_PASSWORD", ""), + "NAME": os.environ.get("TIDB_DATABASE", "test"), + "OPTIONS": { + "charset": "utf8mb4", + }, + } +} + +TIDB_CA_PATH = os.environ.get("TIDB_CA_PATH", "") +if TIDB_CA_PATH: + DATABASES["default"]["OPTIONS"]["ssl_mode"] = "VERIFY_IDENTITY" + DATABASES["default"]["OPTIONS"]["ssl"] = { + "ca": TIDB_CA_PATH, + } +``` + +你可以在项目的根目录下创建一个 `.env` 文件,在文件中添加环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`,并根据你的 TiDB 集群的实际值来设置这些变量的值。 + +### 创建向量表 + +#### 定义向量列 + +`tidb-django` 提供了一个 `VectorField`,可以在表中用来表示和存储向量类型。 + +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 + +```python +class Document(models.Model): + content = models.TextField() + embedding = VectorField(dimensions=3) +``` + +### 存储包含向量的 `document` + +```python +Document.objects.create(content="dog", embedding=[1, 2, 1]) +Document.objects.create(content="fish", embedding=[1, 2, 4]) +Document.objects.create(content="tree", embedding=[1, 0, 0]) +``` + +### 搜索近邻向量 + +TiDB 向量支持以下距离函数: + +- `L1Distance` +- `L2Distance` +- `CosineDistance` +- `NegativeInnerProduct` + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 + +```python +results = Document.objects.annotate( + distance=CosineDistance('embedding', [1, 2, 3]) +).order_by('distance')[:3] +``` + +### 搜索一定距离内的向量 + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 + +```python +results = Document.objects.annotate( + distance=CosineDistance('embedding', [1, 2, 3]) +).filter(distance__lt=0.2).order_by('distance')[:3] +``` + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md new file mode 100644 index 000000000000..c360a24ef7db --- /dev/null +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -0,0 +1,276 @@ +--- +title: 结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索 +summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索,以存储向量嵌入信息并执行语义搜索。 +--- + +# 结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索 + +本文档将展示如何使用 [Jina AI](https://jina.ai/) 为文本数据生成向量嵌入,然后将向量嵌入存储在 TiDB 中,并根据向量嵌入搜索相似文本。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 运行示例应用程序 + +您可以通过以下步骤快速了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索。 + +### 第 1 步:克隆示例代码仓库 + +将 `tidb-vector-python` 仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 第 2 步:创建虚拟环境 + +为你的项目创建虚拟环境: + +```bash +cd tidb-vector-python/examples/jina-ai-embeddings-demo +python3 -m venv .venv +source .venv/bin/activate +``` + +### 第 3 步:安装所需的依赖 + +安装项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +### 第 4 步:配置环境变量 + +从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥,然后根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ +对于本地部署的 TiDB,你可以通过在终端中直接设置环境变量以连接 TiDB 集群: + +```shell +export JINA_API_KEY="****" +export TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如:export TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +``` + +请替换命令中的参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,`HOST` 默认为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤配置 TiDB 连接参数: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `SQLAlchemy`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + +4. 点击 **PyMySQL** 选项卡,复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在终端中将 Jina AI API 密钥以及连接字符串设置为环境变量,或创建一个包含以下环境变量的 `.env` 文件。 + + ```dotenv + JINAAI_API_KEY="****" + TIDB_DATABASE_URL="{tidb_connection_string}" + ``` + + 以下为 macOS 上的连接字符串示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +
+
+ +### 第 5 步:运行示例应用程序 + +```bash +python jina-ai-embeddings-demo.py +``` + +示例输出: + +```text +- Inserting Data to TiDB... + - Inserting: Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI. + - Inserting: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +- List All Documents and Their Distances to the Query: + - distance: 0.3585317326132522 + content: Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI. + - distance: 0.10858102967720984 + content: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +- The Most Relevant Document and Its Distance to the Query: + - distance: 0.10858102967720984 + content: TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. +``` + +## 示例代码片段 + +### 通过 Jina AI 获取嵌入信息 + +定义一个 `generate_embeddings` 函数,用于调用 Jina AI 的嵌入 API: + +```python +import os +import requests +import dotenv + +dotenv.load_dotenv() + +JINAAI_API_KEY = os.getenv('JINAAI_API_KEY') + +def generate_embeddings(text: str): + JINAAI_API_URL = 'https://api.jina.ai/v1/embeddings' + JINAAI_HEADERS = { + 'Content-Type': 'application/json', + 'Authorization': f'Bearer {JINAAI_API_KEY}' + } + JINAAI_REQUEST_DATA = { + 'input': [text], + 'model': 'jina-embeddings-v2-base-en' # with dimension 768. + } + response = requests.post(JINAAI_API_URL, headers=JINAAI_HEADERS, json=JINAAI_REQUEST_DATA) + return response.json()['data'][0]['embedding'] +``` + +### 连接到 TiDB 集群 + +通过 SQLAlchemy 连接 TiDB 集群: + +```python +import os +import dotenv + +from tidb_vector.sqlalchemy import VectorType +from sqlalchemy.orm import Session, declarative_base + +dotenv.load_dotenv() + +TIDB_DATABASE_URL = os.getenv('TIDB_DATABASE_URL') +assert TIDB_DATABASE_URL is not None +engine = create_engine(url=TIDB_DATABASE_URL, pool_recycle=300) +``` + +### 定义向量表结构 + +创建一张 `jinaai_tidb_demo_documents` 表,其中包含一个 `content` 列用于存储文本,一个 `content_vec` 向量列用于存储向量嵌入: + +```python +from sqlalchemy import Column, Integer, String, create_engine +from sqlalchemy.orm import declarative_base + +Base = declarative_base() + +class Document(Base): + __tablename__ = "jinaai_tidb_demo_documents" + + id = Column(Integer, primary_key=True) + content = Column(String(255), nullable=False) + content_vec = Column( + # DIMENSIONS is determined by the embedding model, + # for Jina AI's jina-embeddings-v2-base-en model it's 768. + VectorType(dim=768) + ) +``` + +> **注意:** +> +> - 向量列的维度必须与嵌入模型生成的向量嵌入维度相同。 +> - 在本例中,`jina-embeddings-v2-base-en` 模型生成的向量嵌入维度为 `768`。 + +### 使用 Jina AI 生成向量嵌入并存入 TiDB + +使用 Jina AI 嵌入 API 为每条文本生成向量嵌入,并将这些向量存储在 TiDB 中: + +```python +TEXTS = [ + 'Jina AI offers best-in-class embeddings, reranker and prompt optimizer, enabling advanced multimodal AI.', + 'TiDB is an open-source MySQL-compatible database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads.', +] +data = [] + +for text in TEXTS: + # 通过 Jina AI API 生成文本的向量嵌入 + embedding = generate_embeddings(text) + data.append({ + 'text': text, + 'embedding': embedding + }) + +with Session(engine) as session: + print('- Inserting Data to TiDB...') + for item in data: + print(f' - Inserting: {item["text"]}') + session.add(Document( + content=item['text'], + content_vec=item['embedding'] + )) + session.commit() +``` + +### 使用 Jina AI 生成的向量嵌入在 TiDB 中执行语义搜索 + +通过 Jina AI 的嵌入 API 生成查询文本的向量嵌入,然后根据**查询文本的向量嵌入**和**向量表中各个向量嵌入**之间的余弦距离搜索最相关的 `document`: + +```python +query = 'What is TiDB?' +# 通过 Jina AI API 生成查询文本的向量嵌入 +query_embedding = generate_embeddings(query) + +with Session(engine) as session: + print('- The Most Relevant Document and Its Distance to the Query:') + doc, distance = session.query( + Document, + Document.content_vec.cosine_distance(query_embedding).label('distance') + ).order_by( + 'distance' + ).limit(1).first() + print(f' - distance: {distance}\n' + f' content: {doc.content}') +``` + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md new file mode 100644 index 000000000000..b87518db90d5 --- /dev/null +++ b/vector-search-integrate-with-langchain.md @@ -0,0 +1,637 @@ +--- +title: 在 LangChain 中使用 TiDB 向量搜索 +summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 +--- + +# 在 LangChain 中使用 TiDB 向量搜索 + +本文档将展示如何在 [LangChain](https://python.langchain.com/) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +> **Tip** +> +> 你可以在 Jupyter Notebook 上查看完整的[示例代码](https://github.com/langchain-ai/langchain/blob/master/docs/docs/integrations/vectorstores/tidb_vector.ipynb),也可以直接在 [Colab](https://colab.research.google.com/github/langchain-ai/langchain/blob/master/docs/docs/integrations/vectorstores/tidb_vector.ipynb) 在线环境中运行示例代码。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Jupyter Notebook](https://jupyter.org/install) +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 快速开始 + +本节将详细介绍如何将 TiDB 的向量搜索功能与 LangChain 结合使用,以实现语义搜索。 + +### 第 1 步:新建 Jupyter Notebook 文件 + +在根目录下,新建一个名为 `integrate_with_langchain.ipynb` 的 Jupyter Notebook 文件: + +```shell +touch integrate_with_langchain.ipynb +``` + +### 第 2 步:安装所需的依赖 + +在你的项目目录下,运行以下命令安装所需的软件包: + +```shell +pip install langchain langchain-community +pip install langchain-openai +pip install pymysql +pip install tidb-vector +``` + +在 Jupyter Notebook 中打开 `integrate_with_langchain.ipynb` 文件,添加以下代码以导入所需的软件包: + +```python +from langchain_community.document_loaders import TextLoader +from langchain_community.vectorstores import TiDBVectorStore +from langchain_openai import OpenAIEmbeddings +from langchain_text_splitters import CharacterTextSplitter +``` + +### 第 3 步:配置环境变量 + +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + +运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: + +```python +# Use getpass to securely prompt for environment variables in your terminal. +import getpass +import os + +# Copy your connection string from the TiDB Cloud console. +# Connection string format: "mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +tidb_connection_string = getpass.getpass("TiDB Connection String:") +os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") +``` + +以 macOS 为例,集群的连接字符串如下所示: + +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如:TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +``` + +请替换连接字符串中的参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 `HOST` 地址为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `SQLAlchemy`。 + - **Operating System** 为你的运行环境。 + +4. 点击 **PyMySQL** 选项卡,复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 配置环境变量。 + + 本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从上一步中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + + 运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: + + ```python + # Use getpass to securely prompt for environment variables in your terminal. + import getpass + import os + + # Copy your connection string from the TiDB Cloud console. + # Connection string format: "mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + tidb_connection_string = getpass.getpass("TiDB Connection String:") + os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") + ``` + +
+ +
+ +### 第 4 步:加载样本文档 + +#### 4.1 下载样本文档 + +在你的项目目录中创建一个名为 `data/how_to/` 的目录,然后从 [langchain-ai/langchain](https://github.com/langchain-ai/langchain) 代码库中下载样本文档 [`state_of_the_union.txt`](https://github.com/langchain-ai/langchain/blob/master/docs/docs/how_to/state_of_the_union.txt)。 + +```shell +mkdir -p 'data/how_to/' +wget 'https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/how_to/state_of_the_union.txt' -O 'data/how_to/state_of_the_union.txt' +``` + +#### 4.2 加载并分割文档 + +从 `data/how_to/state_of_the_union.txt` 中加载示例文档,并使用 `CharacterTextSplitter` 将其分割成每块约 1000 个字符的文本块。 + +```python +loader = TextLoader("data/how_to/state_of_the_union.txt") +documents = loader.load() +text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) +docs = text_splitter.split_documents(documents) +``` + +### 第 5 步:生成并存储文档向量 + +TiDB 支持使用余弦距离 (`cosine`) 和欧式距离 (`L2`) 来评估向量之间的相似性。在存储向量时,默认使用余弦距离。 + +以下代码将在 TiDB 中创建一个 `embedded_documents` 表,该表针对向量搜索进行了优化。 + +```python +embeddings = OpenAIEmbeddings() +vector_store = TiDBVectorStore.from_documents( + documents=docs, + embedding=embeddings, + table_name="embedded_documents", + connection_string=tidb_connection_string, + distance_strategy="cosine", # default, another option is "l2" +) +``` + +成功执行后,你可以直接查看和访问 TiDB 数据库中的 `embedded_documents` 表。 + +### 第 6 步:执行向量搜索 + +本节将展示如何在 `state_of_the_union.txt` 文档中查询 "What did the president say about Ketanji Brown Jackson"。 + +```python +query = "What did the president say about Ketanji Brown Jackson" +``` + +#### 方式一:使用 `similarity_search_with_score()` + +`similarity_search_with_score()` 方法用于计算文档内容与查询语句之间的向量距离。该距离是一个相似度的得分,其计算方式由所选的 `distance_strategy` 决定。该方法会返回得分最低的前 `k` 个文档。得分越低,说明文档与你的查询语句之间的相似度越高。 + +```python +docs_with_score = vector_store.similarity_search_with_score(query, k=3) +for doc, score in docs_with_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +
+ 预期输出 + +```plain +-------------------------------------------------------------------------------- +Score: 0.18472413652518527 +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.21757513022785557 +A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since she’s been nominated, she’s received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. + +And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. + +We can do both. At our border, we’ve installed new technology like cutting-edge scanners to better detect drug smuggling. + +We’ve set up joint patrols with Mexico and Guatemala to catch more human traffickers. + +We’re putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. + +We’re securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.22676987253721725 +And for our LGBTQ+ Americans, let’s finally get the bipartisan Equality Act to my desk. The onslaught of state laws targeting transgender Americans and their families is wrong. + +As I said last year, especially to our younger transgender Americans, I will always have your back as your President, so you can be yourself and reach your God-given potential. + +While it often appears that we never agree, that isn’t true. I signed 80 bipartisan bills into law last year. From preventing government shutdowns to protecting Asian-Americans from still-too-common hate crimes to reforming military justice. + +And soon, we’ll strengthen the Violence Against Women Act that I first wrote three decades ago. It is important for us to show the nation that we can come together and do big things. + +So tonight I’m offering a Unity Agenda for the Nation. Four big things we can do together. + +First, beat the opioid epidemic. +-------------------------------------------------------------------------------- +``` + +
+ +#### 方式二:使用 `similarity_search_with_relevance_scores()` 方法 + +`similarity_search_with_relevance_scores()` 方法会返回相关性得分最高的前 `k`个文档。分数越高,说明文档内容与你的查询语句之间的相似度越高。 + +```python +docs_with_relevance_score = vector_store.similarity_search_with_relevance_scores(query, k=2) +for doc, score in docs_with_relevance_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +
+ 预期输出 + +```plain +-------------------------------------------------------------------------------- +Score: 0.8152758634748147 +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Score: 0.7824248697721444 +A former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since she’s been nominated, she’s received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. + +And if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. + +We can do both. At our border, we’ve installed new technology like cutting-edge scanners to better detect drug smuggling. + +We’ve set up joint patrols with Mexico and Guatemala to catch more human traffickers. + +We’re putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. + +We’re securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders. +-------------------------------------------------------------------------------- +``` + +
+ +### 用作检索器 + +在 Langchain 中,[检索器](https://python.langchain.com/v0.2/docs/concepts/#retrievers)是一个接口,用于响应非结构化查询,检索相关文档。相比于向量存储,检索器可以为你提供更多的功能。以下代码演示了如何将 TiDB 向量存储用作检索器。 + +```python +retriever = vector_store.as_retriever( + search_type="similarity_score_threshold", + search_kwargs={"k": 3, "score_threshold": 0.8}, +) +docs_retrieved = retriever.invoke(query) +for doc in docs_retrieved: + print("-" * 80) + print(doc.page_content) + print("-" * 80) +``` + +预期输出如下: + +``` +-------------------------------------------------------------------------------- +Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. + +Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. + +One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. + +And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence. +-------------------------------------------------------------------------------- +``` + +### 移除向量存储 + +要删除现有的 TiDB 向量存储,可以使用 `drop_vectorstore()` 方法: + +```python +vector_store.drop_vectorstore() +``` + +## 使用元数据过滤器进行搜索 + +为了优化搜索,你可以使用元数据过滤器来筛选出符合特定条件的近邻结果。 + +### 支持的元数据类型 + +在 TiDB 向量存储中,每个文档都可以与元数据配对。元数据的结构是 JSON 对象中的键值对 (key-value pairs) 形式。键 (key) 的类型是字符串,而值 (value) 可以是以下任何类型: + +- 字符串 +- 数值:整数或浮点数 +- Boolean:`true` 或 `false` + +例如,下面是一个有效的元数据格式: + +```json +{ + "page": 12, + "book_title": "Siddhartha" +} +``` + +### 元数据过滤器语法 + +可用的过滤器包括: + +- `$or`:选择符合任意一个指定条件的向量。 +- `$and`:选择符合所有指定条件的向量。 +- `$eq`:等于指定值。 +- `$ne`:不等于指定值。 +- `$gt`:大于指定值。 +- `$gte`:大于或等于指定值。 +- `$lt`:小于指定值。 +- `$lte`:小于或等于指定值。 +- `$in`:在指定的值数组中。 +- `$nin`:不在指定值数组中。 + +假如一个文档的元数据如下: + +```json +{ + "page": 12, + "book_title": "Siddhartha" +} +``` + +以下元数据筛选器均可匹配到该文档: + +```json +{ "page": 12 } +``` + +```json +{ "page": { "$eq": 12 } } +``` + +```json +{ + "page": { + "$in": [11, 12, 13] + } +} +``` + +```json +{ "page": { "$nin": [13] } } +``` + +```json +{ "page": { "$lt": 11 } } +``` + +```json +{ + "$or": [{ "page": 11 }, { "page": 12 }], + "$and": [{ "page": 12 }, { "page": 13 }] +} +``` + +TiDB 会将元数据过滤器中的每个键值对视为一个独立的过滤条件,并使用 `AND` 逻辑操作符将这些条件组合起来。 + +### 示例 + +以下示例代码向 `TiDBVectorStore` 添加了两个文档,并为每个文档添加了一个 `title` 字段作为元数据: + +```python +vector_store.add_texts( + texts=[ + "TiDB Vector offers advanced, high-speed vector processing capabilities, enhancing AI workflows with efficient data handling and analytics support.", + "TiDB Vector, starting as low as $10 per month for basic usage", + ], + metadatas=[ + {"title": "TiDB Vector functionality"}, + {"title": "TiDB Vector Pricing"}, + ], +) +``` + +预期输出如下: + +```plain +[UUID('c782cb02-8eec-45be-a31f-fdb78914f0a7'), + UUID('08dcd2ba-9f16-4f29-a9b7-18141f8edae3')] +``` + +使用元数据过滤器进行相似性搜索: + +```python +docs_with_score = vector_store.similarity_search_with_score( + "Introduction to TiDB Vector", filter={"title": "TiDB Vector functionality"}, k=4 +) +for doc, score in docs_with_score: + print("-" * 80) + print("Score: ", score) + print(doc.page_content) + print("-" * 80) +``` + +预期输出如下: + +```plain +-------------------------------------------------------------------------------- +Score: 0.12761409169211535 +TiDB Vector offers advanced, high-speed vector processing capabilities, enhancing AI workflows with efficient data handling and analytics support. +-------------------------------------------------------------------------------- +``` + +## 进阶用法示例:旅行代理 + +本节演示如何将 Langchain 和 TiDB 向量搜索相结合,应用于旅行代理的场景。该场景的目标是为客户创建个性化的旅行报告,帮助他们找到具备特定设施(例如干净的休息室和素食选项)的机场。 + +该示例包括两个主要步骤: + +1. 对机场介绍中进行语义搜索,以找出符合所需设施的机场代码。 +2. 执行 SQL 查询,将这些代码与航线信息相结合,以便突出显示符合用户偏好的航空公司和目的地。 + +### 准备数据 + +首先,创建一个表来存储机场航线数据: + +```python +# 创建表格以存储飞行计划数据。 +vector_store.tidb_vector_client.execute( + """CREATE TABLE airplan_routes ( + id INT AUTO_INCREMENT PRIMARY KEY, + airport_code VARCHAR(10), + airline_code VARCHAR(10), + destination_code VARCHAR(10), + route_details TEXT, + duration TIME, + frequency INT, + airplane_type VARCHAR(50), + price DECIMAL(10, 2), + layover TEXT + );""" +) + +# 在 airplan_routes 和向量表中插入一些样本数据。 +vector_store.tidb_vector_client.execute( + """INSERT INTO airplan_routes ( + airport_code, + airline_code, + destination_code, + route_details, + duration, + frequency, + airplane_type, + price, + layover + ) VALUES + ('JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', '06:00:00', 5, 'Boeing 777', 299.99, 'None'), + ('LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', '04:00:00', 3, 'Airbus A320', 149.99, 'None'), + ('EFGH', 'UA', 'SEA', 'Daily flights from SFO to SEA.', '02:30:00', 7, 'Boeing 737', 129.99, 'None'); + """ +) +vector_store.add_texts( + texts=[ + "Clean lounges and excellent vegetarian dining options. Highly recommended.", + "Comfortable seating in lounge areas and diverse food selections, including vegetarian.", + "Small airport with basic facilities.", + ], + metadatas=[ + {"airport_code": "JFK"}, + {"airport_code": "LAX"}, + {"airport_code": "EFGH"}, + ], +) +``` + +预期输出如下: + +```plain +[UUID('6dab390f-acd9-4c7d-b252-616606fbc89b'), + UUID('9e811801-0e6b-4893-8886-60f4fb67ce69'), + UUID('f426747c-0f7b-4c62-97ed-3eeb7c8dd76e')] +``` + +### 执行语义搜索 + +以下代码可以搜索到有清洁设施和素食选择的机场: + +```python +retriever = vector_store.as_retriever( + search_type="similarity_score_threshold", + search_kwargs={"k": 3, "score_threshold": 0.85}, +) +semantic_query = "Could you recommend a US airport with clean lounges and good vegetarian dining options?" +reviews = retriever.invoke(semantic_query) +for r in reviews: + print("-" * 80) + print(r.page_content) + print(r.metadata) + print("-" * 80) +``` + +预期输出如下: + +```plain +-------------------------------------------------------------------------------- +Clean lounges and excellent vegetarian dining options. Highly recommended. +{'airport_code': 'JFK'} +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Comfortable seating in lounge areas and diverse food selections, including vegetarian. +{'airport_code': 'LAX'} +-------------------------------------------------------------------------------- +``` + +### 检索详细的机场信息 + +从搜索结果中提取机场代码,查询数据库中的详细航线信息: + +```python +# Extracting airport codes from the metadata +airport_codes = [review.metadata["airport_code"] for review in reviews] + +# Executing a query to get the airport details +search_query = "SELECT * FROM airplan_routes WHERE airport_code IN :codes" +params = {"codes": tuple(airport_codes)} + +airport_details = vector_store.tidb_vector_client.execute(search_query, params) +airport_details.get("result") +``` + +预期输出如下: + +```plain +[(1, 'JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', datetime.timedelta(seconds=21600), 5, 'Boeing 777', Decimal('299.99'), 'None'), + (2, 'LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', datetime.timedelta(seconds=14400), 3, 'Airbus A320', Decimal('149.99'), 'None')] +``` + +### 简化流程 + +你也可以使用单个 SQL 查询来简化整个流程: + +```python +search_query = f""" + SELECT + VEC_Cosine_Distance(se.embedding, :query_vector) as distance, + ar.*, + se.document as airport_review + FROM + airplan_routes ar + JOIN + {TABLE_NAME} se ON ar.airport_code = JSON_UNQUOTE(JSON_EXTRACT(se.meta, '$.airport_code')) + ORDER BY distance ASC + LIMIT 5; +""" +query_vector = embeddings.embed_query(semantic_query) +params = {"query_vector": str(query_vector)} +airport_details = vector_store.tidb_vector_client.execute(search_query, params) +airport_details.get("result") +``` + +预期输出如下: + +```plain +[(0.1219207353407008, 1, 'JFK', 'DL', 'LAX', 'Non-stop from JFK to LAX.', datetime.timedelta(seconds=21600), 5, 'Boeing 777', Decimal('299.99'), 'None', 'Clean lounges and excellent vegetarian dining options. Highly recommended.'), + (0.14613754359804654, 2, 'LAX', 'AA', 'ORD', 'Direct LAX to ORD route.', datetime.timedelta(seconds=14400), 3, 'Airbus A320', Decimal('149.99'), 'None', 'Comfortable seating in lounge areas and diverse food selections, including vegetarian.'), + (0.19840519342700513, 3, 'EFGH', 'UA', 'SEA', 'Daily flights from SFO to SEA.', datetime.timedelta(seconds=9000), 7, 'Boeing 737', Decimal('129.99'), 'None', 'Small airport with basic facilities.')] +``` + +### 清理数据 + +最后,删除创建的表,清理资源: + +```python +vector_store.tidb_vector_client.execute("DROP TABLE airplan_routes") +``` + +预期输出如下: + +```plain +{'success': True, 'result': 0, 'error': None} +``` + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md new file mode 100644 index 000000000000..27332841d6ff --- /dev/null +++ b/vector-search-integrate-with-llamaindex.md @@ -0,0 +1,315 @@ +--- +title: 在 LlamaIndex 中使用 TiDB 向量搜索 +summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 +--- + +# 在 LlamaIndex 中使用 TiDB 向量搜索 + +本文档将展示如何在 [LlamaIndex](https://www.llamaindex.ai) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +> **Tip** +> +> 你可以在 Jupyter Notebook 上查看完整的[示例代码](https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/vector_stores/TiDBVector.ipynb),或直接在 [Colab](https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/docs/examples/vector_stores/TiDBVector.ipynb) 在线环境中运行示例代码。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Jupyter Notebook](https://jupyter.org/install) +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 快速开始 + +本节将详细介绍如何将 TiDB 的向量搜索功能与 LlamaIndex 结合使用,以实现语义搜索。 + +### 第 1 步:新建 Jupyter Notebook 文件 + +在根目录下,新建一个名为 `integrate_with_llamaindex.ipynb` 的 Jupyter Notebook 文件: + +```shell +touch integrate_with_llamaindex.ipynb +``` + +### 第 2 步:安装所需的依赖 + +在你的项目目录下,运行以下命令安装所需的软件包: + +```shell +pip install llama-index-vector-stores-tidbvector +pip install llama-index +``` + +在 Jupyter Notebook 中打开 `integrate_with_llamaindex.ipynb` 文件,添加以下代码以导入所需的软件包: + +```python +import textwrap + +from llama_index.core import SimpleDirectoryReader, StorageContext +from llama_index.core import VectorStoreIndex +from llama_index.vector_stores.tidbvector import TiDBVectorStore +``` + +### 第 3 步:配置环境变量 + + + +
+ +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + +运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: + +```python +# Use getpass to securely prompt for environment variables in your terminal. +import getpass +import os + +# Copy your connection string from the TiDB Cloud console. +# Connection string format: "mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +tidb_connection_string = getpass.getpass("TiDB Connection String:") +os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") +``` + +以 macOS 为例,集群的连接字符串如下所示: + +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +``` + +请替换连接字符串中的参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 `HOST` 地址为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取 TiDB 集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `SQLAlchemy`。 + - **Operating System** 为你的运行环境。 + +4. 点击 **PyMySQL** 选项卡,复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 配置环境变量。 + + 本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从上一步中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 + + 运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: + + ```python + # Use getpass to securely prompt for environment variables in your terminal. + import getpass + import os + + # Copy your connection string from the TiDB Cloud console. + # Connection string format: "mysql+pymysql://:@:4000/?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + tidb_connection_string = getpass.getpass("TiDB Connection String:") + os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") + ``` + +
+ +
+ +### 第 4 步:加载样本文档 + +#### 4.1 下载样本文档 + +在你的项目目录中创建一个名为 `data/paul_graham/` 的目录,然后从 [run-llama/llama_index](https://github.com/run-llama/llama_index) GitHub 代码库中下载样本文档 [`paul_graham_essay.txt`](https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt): + +```shell +mkdir -p 'data/paul_graham/' +wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt' +``` + +#### 4.2 加载文档 + +使用 `SimpleDirectoryReader` 从 `data/paul_graham/paul_graham_essay.txt` 中加载示例文档: + +```python +documents = SimpleDirectoryReader("./data/paul_graham").load_data() +print("Document ID:", documents[0].doc_id) + +for index, document in enumerate(documents): + document.metadata = {"book": "paul_graham"} +``` + +### 第 5 步:生成并存储文档向量 + +#### 5.1 初始化 TiDB 向量存储 + +以下代码将在 TiDB 中创建一个 `paul_graham_test` 表,该表针对向量搜索进行了优化。 + +```python +tidbvec = TiDBVectorStore( + connection_string=tidb_connection_url, + table_name="paul_graham_test", + distance_strategy="cosine", + vector_dimension=1536, + drop_existing_table=False, +) +``` + +执行成功后,你可以直接查看和访问 TiDB 数据库中的 `paul_graham_test` 表。 + +#### 5.2 生成并存储向量嵌入 + +以下代码将解析文档以生成向量嵌入,并将向量嵌入存储到 TiDB 向量存储中。 + +```python +storage_context = StorageContext.from_defaults(vector_store=tidbvec) +index = VectorStoreIndex.from_documents( + documents, storage_context=storage_context, show_progress=True +) +``` + +预期输出如下: + +```plain +Parsing nodes: 100%|██████████| 1/1 [00:00<00:00, 8.76it/s] +Generating embeddings: 100%|██████████| 21/21 [00:02<00:00, 8.22it/s] +``` + +### 第 6 步:执行向量搜索 + +以下代码将基于 TiDB 向量存储创建一个查询引擎,并执行语义相似性搜索。 + +```python +query_engine = index.as_query_engine() +response = query_engine.query("What did the author do?") +print(textwrap.fill(str(response), 100)) +``` + +> **注意:** +> +> `TiDBVectorStore` 只支持 [`default`](https://docs.llamaindex.ai/en/stable/api_reference/storage/vector_store/?h=vectorstorequerymode#llama_index.core.vector_stores.types.VectorStoreQueryMode) 查询模式。 + +预期输出如下: + +```plain +The author worked on writing, programming, building microcomputers, giving talks at conferences, +publishing essays online, developing spam filters, painting, hosting dinner parties, and purchasing +a building for office use. +``` + +### 第 7 步:使用元数据过滤器进行搜索 + +为了优化搜索,你可以使用元数据过滤器来筛选出符合特定条件的近邻结果。 + +#### 使用 `book != “paul_graham”` 过滤器查询 + +以下示例的查询将排除掉 `book` 元数据字段为 `paul_graham` 的结果: + +```python +from llama_index.core.vector_stores.types import ( + MetadataFilter, + MetadataFilters, +) + +query_engine = index.as_query_engine( + filters=MetadataFilters( + filters=[ + MetadataFilter(key="book", value="paul_graham", operator="!="), + ] + ), + similarity_top_k=2, +) +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +Empty Response +``` + +#### Query with `book == "paul_graham"` filter + +以下示例的查询将筛选出 `book` 元数据字段为 `paul_graham` 的结果: + +```python +from llama_index.core.vector_stores.types import ( + MetadataFilter, + MetadataFilters, +) + +query_engine = index.as_query_engine( + filters=MetadataFilters( + filters=[ + MetadataFilter(key="book", value="paul_graham", operator="=="), + ] + ), + similarity_top_k=2, +) +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +The author learned programming on an IBM 1401 using an early version of Fortran in 9th grade, then +later transitioned to working with microcomputers like the TRS-80 and Apple II. Additionally, the +author studied philosophy in college but found it unfulfilling, leading to a switch to studying AI. +Later on, the author attended art school in both the US and Italy, where they observed a lack of +substantial teaching in the painting department. +``` + +### 第 8 步:删除文档 + +从索引中删除第一个文档: + +```python +tidbvec.delete(documents[0].doc_id) +``` + +检查文档是否已被删除: + +```python +query_engine = index.as_query_engine() +response = query_engine.query("What did the author learn?") +print(textwrap.fill(str(response), 100)) +``` + +预期输出如下: + +```plain +Empty Response +``` + +## 另请参阅 + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md new file mode 100644 index 000000000000..0d3adfadb957 --- /dev/null +++ b/vector-search-integrate-with-peewee.md @@ -0,0 +1,254 @@ +--- +title: 在 peewee 中使用 TiDB 向量搜索 +summary: 了解如何在 peewee 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 +--- + +# 在 peewee 中使用 TiDB 向量搜索 + +本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 运行示例应用程序 + +你可以通过以下步骤快速了解如何在 peewee 中使用 TiDB 向量搜索。 + +### 第 1 步:克隆示例代码仓库 + +将 [`tidb-vector-python`](https://github.com/pingcap/tidb-vector-python) 仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 第 2 步:创建虚拟环境 + +为你的项目创建虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-peewee-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 第 3 步:安装所需的依赖 + +安装项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +你也可以直接为项目安装以下依赖项: + +```bash +pip install peewee pymysql python-dotenv tidb-vector +``` + +### 第 4 步:配置环境变量 + +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: + +```dotenv +TIDB_HOST=127.0.0.1 +TIDB_PORT=4000 +TIDB_USERNAME=root +TIDB_PASSWORD= +TIDB_DATABASE=test +``` + +如果你在本机运行 TiDB,`TIDB_HOST` 默认为 `127.0.0.1`。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- `TIDB_HOST`:TiDB 集群的主机号。 +- `TIDB_PORT`:TiDB 集群的端口号。 +- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 +- `TIDB_DATABASE`:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与你的机器环境相匹配 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + +4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 + + - `TIDB_HOST`:TiDB 集群的主机号。 + - `TIDB_PORT`:TiDB 集群的端口号。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 + + 以下为 MacOS 的示例: + + ```dotenv + TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_PORT=4000 + TIDB_USERNAME=********.root + TIDB_PASSWORD=******** + TIDB_DATABASE=test + TIDB_CA_PATH=/etc/ssl/cert.pem + ``` + +
+ +
+ +### 第 5 步:运行示例应用程序 + +```bash +python peewee-quickstart.py +``` + +输出示例: + +```text +Get 3-nearest neighbor documents: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog + - distance: 0.7327387580875756 + document: tree +Get documents within a certain distance: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog +``` + +## 示例代码片段 + +你可以参考以下示例代码片段来完成自己的应用程序开发。 + +### 创建向量表 + +#### 连接到 TiDB 集群 + +```python +import os +import dotenv + +from peewee import Model, MySQLDatabase, SQL, TextField +from tidb_vector.peewee import VectorField + +dotenv.load_dotenv() + +# Using `pymysql` as the driver. +connect_kwargs = { + 'ssl_verify_cert': True, + 'ssl_verify_identity': True, +} + +# Using `mysqlclient` as the driver. +# connect_kwargs = { +# 'ssl_mode': 'VERIFY_IDENTITY', +# 'ssl': { +# # Root certificate default path. +# # If you are using a tidb serverless cluster, +# # you can refer to the following link to configure "TIDB_CA_PATH". +# # https://docs.pingcap.com/tidbcloud/secure-connections-to-serverless-clusters/#root-certificate-default-path +# 'ca': os.environ.get('TIDB_CA_PATH', '/path/to/ca.pem'), +# }, +# } + +db = MySQLDatabase( + database=os.environ.get('TIDB_DATABASE', 'test'), + user=os.environ.get('TIDB_USERNAME', 'root'), + password=os.environ.get('TIDB_PASSWORD', ''), + host=os.environ.get('TIDB_HOST', 'localhost'), + port=int(os.environ.get('TIDB_PORT', '4000')), + **connect_kwargs, +) +``` + +#### 定义向量列 + +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 + +```python +class Document(Model): + class Meta: + database = db + table_name = 'peewee_demo_documents' + + content = TextField() + embedding = VectorField(3) +``` + +### 存储包含向量的 `document` + +```python +Document.create(content='dog', embedding=[1, 2, 1]) +Document.create(content='fish', embedding=[1, 2, 4]) +Document.create(content='tree', embedding=[1, 0, 0]) +``` + +### 搜索近邻向量 + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 + +```python +distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') +results = Document.select(Document, distance).order_by(distance).limit(3) +``` + +### 搜索一定距离内的向量 + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 + +```python +distance_expression = Document.embedding.cosine_distance([1, 2, 3]) +distance = distance_expression.alias('distance') +results = Document.select(Document, distance).where(distance_expression < 0.2).order_by(distance).limit(3) +``` + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md new file mode 100644 index 000000000000..5aae29e0c61e --- /dev/null +++ b/vector-search-integrate-with-sqlalchemy.md @@ -0,0 +1,222 @@ +--- +title: 在 SQLAlchemy 中使用 TiDB 向量搜索 +summary: 了解如何在 SQLAlchemy 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 +--- + +# 在 SQLAlchemy 中使用 TiDB 向量搜索 + +本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 前置需求 + +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 运行示例应用程序 + +你可以通过以下步骤快速了解如何在 SQLAlchemy 中使用 TiDB 向量搜索。 + +### 第 1 步:克隆示例代码仓库 + +将 `tidb-vector-python` 仓库克隆到本地: + +```shell +git clone https://github.com/pingcap/tidb-vector-python.git +``` + +### 第 2 步:创建虚拟环境 + +为你的项目创建虚拟环境: + +```bash +cd tidb-vector-python/examples/orm-sqlalchemy-quickstart +python3 -m venv .venv +source .venv/bin/activate +``` + +### 第 3 步:安装所需的依赖 + +安装示例项目所需的依赖: + +```bash +pip install -r requirements.txt +``` + +你也可以直接为项目安装以下依赖项: + +```bash +pip install pymysql python-dotenv sqlalchemy tidb-vector +``` + +### 第 4 步:配置环境变量 + +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: + +```dotenv +TIDB_DATABASE_URL=mysql+pymysql://:@:/ +# 例如:TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +``` + +如果你在本机运行 TiDB,`HOST` 默认为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:TiDB 集群的主机。 +- ``:TiDB 集群的端口。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 + +
+ +
+ +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `General`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 单击 **PyMySQL** 选项卡,复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接字符串粘贴到其中。 + + 以下为 MacOS 的示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +
+
+ +### 第 5 步:运行示例应用程序 + +```bash +python sqlalchemy-quickstart.py +``` + +输出示例: + +```text +Get 3-nearest neighbor documents: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog + - distance: 0.7327387580875756 + document: tree +Get documents within a certain distance: + - distance: 0.00853986601633272 + document: fish + - distance: 0.12712843905603044 + document: dog +``` + +## 示例代码片段 + +你可以参考以下示例代码片段来完成自己的应用程序开发。 + +### 创建向量表 + +#### 连接到 TiDB 集群 + +```python +import os +import dotenv + +from sqlalchemy import Column, Integer, create_engine, Text +from sqlalchemy.orm import declarative_base, Session +from tidb_vector.sqlalchemy import VectorType + +dotenv.load_dotenv() + +tidb_connection_string = os.environ['TIDB_DATABASE_URL'] +engine = create_engine(tidb_connection_string) +``` + +#### 定义向量列 + +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 + +```python +Base = declarative_base() + +class Document(Base): + __tablename__ = 'sqlalchemy_demo_documents' + id = Column(Integer, primary_key=True) + content = Column(Text) + embedding = Column(VectorType(3)) +``` + +### 存储包含向量的 `document` + +```python +with Session(engine) as session: + session.add(Document(content="dog", embedding=[1, 2, 1])) + session.add(Document(content="fish", embedding=[1, 2, 4])) + session.add(Document(content="tree", embedding=[1, 0, 0])) + session.commit() +``` + +### 搜索近邻向量 + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 + +```python +with Session(engine) as session: + distance = Document.embedding.cosine_distance([1, 2, 3]).label('distance') + results = session.query( + Document, distance + ).order_by(distance).limit(3).all() +``` + +### 搜索一定距离内的向量 + +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 + +```python +with Session(engine) as session: + distance = Document.embedding.cosine_distance([1, 2, 3]).label('distance') + results = session.query( + Document, distance + ).filter(distance < 0.2).order_by(distance).limit(3).all() +``` + +## 另请参阅 + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md new file mode 100644 index 000000000000..4a4974f2d871 --- /dev/null +++ b/vector-search-integration-overview.md @@ -0,0 +1,71 @@ +--- +title: 向量搜索集成概览 +summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库。 +--- + +# 向量搜索集成概览 + +本文档介绍了 TiDB 向量搜索支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## AI 框架 + +TiDB 目前支持以下 AI 框架。基于这些 AI 框架,你可以使用 TiDB 向量搜索轻松构建 AI 应用程序。 + +| AI 框架 | 教程 | +|---------------|---------------------------------------------------------------------------------------------------| +| Langchain | [在 LangChain 中使用 TiDB 向量搜索](/vector-search-integrate-with-langchain.md) | +| LlamaIndex | [在 LlamaIndex 中使用 TiDB 向量搜索](/vector-search-integrate-with-llamaindex.md) | + +此外,你还可以使用 TiDB 完成多种其它需求,例如将 TiDB 用于 AI 应用程序的文档存储和知识图谱存储等。 + +## 嵌入模型和服务 + +TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌入模型。 + +你可以使用自行部署的开源嵌入模型或第三方嵌入模型提供商的嵌入 API 来生成向量。 + +下表列出了部分主流嵌入模型服务提供商和相应的集成教程。 + +| 嵌入模型服务提供商 | 教程 | +|-----------------------------|---------------------------------------------------------------------------------------------------------------------| +| Jina AI | [结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索](/vector-search-integrate-with-jinaai-embedding.md) | + +## 对象关系映射 (ORM) 库 + +你可以将 TiDB 向量搜索功能与 ORM 库结合使用,以便与 TiDB 数据库交互。 + +下表列出了支持的 ORM 库和相应的使用教程: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LanguageORM/ClientHow to installTutorial
PythonTiDB Vector Clientpip install tidb-vector[client]使用 Python 开始向量搜索
SQLAlchemypip install tidb-vector在 SQLAlchemy 中使用 TiDB 向量搜索
peeweepip install tidb-vector在 peewee 中使用 TiDB 向量搜索
Djangopip install django-tidb[vector]在 Django 中使用 TiDB 向量搜索
\ No newline at end of file diff --git a/vector-search-limitations.md b/vector-search-limitations.md new file mode 100644 index 000000000000..1c9fae0338b7 --- /dev/null +++ b/vector-search-limitations.md @@ -0,0 +1,24 @@ +--- +title: 向量搜索限制 +summary: 了解 TiDB 向量搜索功能的限制。 +--- + +# 向量搜索限制 + +本文档介绍 TiDB 向量搜索的已知限制。在未来的版本中,我们会持续新增更多功能来提升使用体验。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +- 向量最大支持 16383 维。 +- 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 创建[向量搜索索引](/vector-search-index.md)时的限制,参照[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 +- 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 +- 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 +- DM 不支持 MySQL 9.0 的向量数据类型同步。 +- CDC 对于不支持向量数据的下游会修改数据类型。参照[向量搜索功能兼容性说明](/ticdc/ticdc-compatibility.md#向量搜索功能兼容性说明实验特性) + +## 反馈 + +我们非常重视您的反馈意见。如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 diff --git a/vector-search-overview.md b/vector-search-overview.md new file mode 100644 index 000000000000..157dbcd53e17 --- /dev/null +++ b/vector-search-overview.md @@ -0,0 +1,72 @@ +--- +title: 向量搜索概述 +summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图像、音频和视频等多种数据类型进行语义搜索。 +--- + +# 向量搜索概述 + +TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、图像、音频和视频等多种数据类型之间进行相似度搜索。TiDB 向量搜索的 SQL 语法与 MySQL 兼容,熟悉 MySQL 的开发人员可以基于该功能轻松构建人工智能 (AI) 应用。 + +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + +## 概念 + +向量搜索是一种优先考虑数据语义以提供相关结果的搜索方法。 + +与传统的全文搜索(主要依赖于精确的关键词匹配和词频)不同,向量搜索通过将不同类型的数据(如文本、图像或音频)转换为高维向量,并根据这些向量之间的相似度来进行查询。这种搜索方法能够捕捉数据的语义特征和上下文信息,从而更准确地理解用户意图。 + +即使搜索的词语与数据库中的内容不完全匹配,向量搜索仍然可以通过对数据语义的理解,找到与用户意图相符合的结果。 + +例如,搜索 “一种会游泳的动物” 时,全文搜索只会返回包含这些精确关键词的结果,而向量搜索可以返回其他游泳动物的结果,如鱼或鸭子,即使这些结果并未包含精确的关键词。 + +### 向量嵌入 + +向量嵌入 (vector embedding) 也称为嵌入 (embedding) ,是在高维空间中用于表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的语义特征和上下文。 + +向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 + +TiDB 专门引入了[向量数据类型](/vector-search-data-types.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 + +### 嵌入模型 + +嵌入模型是将数据转换为[向量嵌入](#向量嵌入)的算法。 + +选择一种合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化的文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 + +如需了解如何为特定数据类型生成向量嵌入,请参阅相关嵌入模型的教程或示例。 + +## 工作原理 + +在你将原始数据转换为向量并存储在 TiDB 中后,你的应用程序就可以开始利用这些向量来执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 + +TiDB 向量搜索 (Vector Search) 通过使用[距离函数](/vector-search-functions-and-operators.md)来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。其中,与给定向量距离最小的向量即代表最相似的数据。 + +![The Schematic TiDB Vector Search](/media/vector-search/embedding-search.png) + +TiDB 作为一款关系型数据库,在引入了向量搜索功能后,支持将数据及其对应的向量表示(向量嵌入)存储在同一个数据库中。你可以选择以下任一种存储方式: + +- 将数据和对应的向量表示存储在同一张表的不同列中。 +- 将数据和对应的向量表示分别存储在不同的表中。在进行搜索时,通过 JOIN 查询将这些表关联起来。 + +## 使用场景 + +### 检索增强生成 (Retrieval-Augmented Generation, RAG) + +检索增强生成(RAG)是一种优化大型语言模型(LLM)输出的架构。通过使用向量搜索,RAG 应用程序可以在数据库中存储向量嵌入,并在 LLM 生成回复时检索相关文档作为附加上下文,从而提高回复的质量和相关性。 + +### 语义搜索 + +语义搜索是一种根据查询的含义而不是简单地匹配关键词来返回结果的搜索技术。它将不同语言和各种类型的数据(如文本、图像、音频)的含义转换为向量嵌入。然后,向量搜索算法会使用这些向量嵌入来查找满足用户查询的最相关数据。 + +### 推荐引擎 + +推荐引擎是一种推荐系统,它会主动向用户推荐与他们高度相关且个性化的内容、产品或服务。为了实现这一目标,推荐引擎会创建反映用户行为和偏好的向量嵌入。这些嵌入可以帮助系统识别其他用户曾经互动过或感兴趣的类似项目,从而提高推荐内容与用户的相关性,并增加吸引用户的可能性。 + +## 另请参阅 + +要开始使用 TiDB 向量搜索,请参阅以下文档: + +- [使用 Python 开始向量搜索](/vector-search-get-started-using-python.md) +- [使用 SQL 开始向量搜索](/vector-search-get-started-using-sql.md) \ No newline at end of file