From 48f906c7d51ac19dfca9d659a404a30e9ee4d828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 2 Sep 2024 11:53:41 +0800 Subject: [PATCH 001/109] TiDB vector data type and vector index Doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 248 ++++++++++++++++++ vector-search-functions-and-operators.md | 279 +++++++++++++++++++++ vector-search-index.md | 270 ++++++++++++++++++++ vector-search-integrate-with-django-orm.md | 233 +++++++++++++++++ vector-search-integrate-with-peewee.md | 223 ++++++++++++++++ vector-search-integrate-with-sqlalchemy.md | 196 +++++++++++++++ vector-search-limitations.md | 21 ++ 7 files changed, 1470 insertions(+) create mode 100644 vector-search-data-types.md create mode 100644 vector-search-functions-and-operators.md create mode 100644 vector-search-index.md create mode 100644 vector-search-integrate-with-django-orm.md create mode 100644 vector-search-integrate-with-peewee.md create mode 100644 vector-search-integrate-with-sqlalchemy.md create mode 100644 vector-search-limitations.md diff --git a/vector-search-data-types.md b/vector-search-data-types.md new file mode 100644 index 000000000000..f929188a26a9 --- /dev/null +++ b/vector-search-data-types.md @@ -0,0 +1,248 @@ +--- +title: 向量数据类型 +summary: 本文介绍 TiDB 的向量数据类型。 +--- + +# 向量数据类型(Vector) + +TiDB 提供的矢量数据类型专门针对AI向量嵌入用例进行了优化。通过使用向量数据类型,可以高效地存储和查询浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`. + +目前可用的向量数据类型如下: + +- `VECTOR`: 单精度浮点数序列。每一行的维度可以不同。 +- `VECTOR(D)`: 具有固定维度 `D` 的单精度浮点数序列。 + +与存储在`JSON`列中相比,向量数据类型具有这些优势: + +- 支持向量索引。 可以通过构建[向量搜索索引]()加速查询。 +- 指定维度。可以指定一个维度,禁止插入不同维度的向量。 +- 优化存储格式。向量数据类型的存储空间效率甚至比`JSON`数据类型更高。 + +## Value syntax + +向量值包含任意数量的浮点数,可以使用以下语法中的字符串来表示向量值: + +```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); +``` + +插入语法无效的向量值将导致错误: + +```sql +[tidb]> INSERT INTO vector_table VALUES (3, '[5, ]'); +ERROR 1105 (HY000): Invalid vector text: [5, ] +``` + +在上例中,`embedding`列的维度为 3,因此插入不同维度的向量会导致错误: + +```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 dimensions vector, OK +INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK +``` + +但是,我们不能为此列构建[向量搜索索引](/vector-search-index.md),因为向量距离只能在具有相同维度的向量之间计算。 + +## 对比 + +我们可以使用[比较运算符](/vector-search-functions-and-operators.md)来比较两个向量,如:`=`, `!=`, `<`, `>`, `<=`, and `>=`。有关向量数据类型的比较运算符和函数的完整列表,参阅[向量函数与操作](/vector-search-functions-and-operators.md)。 + +向量数据类型以元素为单位进行比较,例如: + +- `[1] < [12]` +- `[1,2,3] < [1,2,5]` +- `[1,2,3] = [1,2,3]` +- `[2,2,3] > [1,2,3]` + +不同维度的向量采用字典序比较,具有一下特性: + +- 两个矢量逐个元素进行比较,每个元素都以数值形式进行比较。 +- 第一个不匹配的元素决定哪一个向量在字典序上 _less_ 或 _greater_。 +- 如果一个向量是另一个向量的前缀,那么较短的向量为 _less_ 。 +- 长度相同、元素相同的两个向量为 _equal_ 。 +- 空向量是小于任何非空向量。 +- 两个空向量为 _equal_ 。 + +例如: + +- `[] < [1]` +- `[1,2,3] < [1,2,3,0]` + +在比较向量常量时,需要考虑执行从字符串到向量的 [显式转换](#cast),以避免基于字符串值的比较: + +```sql +-- Because string is given, TiDB is comparing strings: +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- Cast to vector explicitly to compare by vectors: +[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) + +mysql> 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(... AS VECTOR)`: String ⇒ Vector +- `CAST(... AS CHAR)`: Vector ⇒ String +- `VEC_FROM_TEXT`: String ⇒ Vector +- `VEC_AS_TEXT`: Vector ⇒ String + +在调用接收向量数据类型的函数时,存在隐式转换: + +```sql +-- There is an implicit cast here, since VEC_DIMS only accepts VECTOR arguments: +[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) + +-- Cast explicitly using VEC_FROM_TEXT: +[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 explicitly using 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) +``` + +当运算符或函数接受多种数据类型时,请使用显式转换。例如,在比较中,使用显式转换来比较向量数值而不是字符串数值: + +```sql +-- Because string is given, TiDB is comparing strings: +[tidb]> SELECT '[12.0]' < '[4.0]'; ++--------------------+ +| '[12.0]' < '[4.0]' | ++--------------------+ +| 1 | ++--------------------+ +1 row in set (0.01 sec) + +-- Cast to vector explicitly to compare by vectors: +[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 +-- String representation is normalized: +[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)。 + +### 向量与其他数据类型之间的转换 + +目前无法直接在向量和其他数据类型(如 `JSON`)之间进行转换。您需要使用字符串作为中间类型。 + +## 约束 + +- 支持的最大向量维数为 16383。 +- 不能在向量数据类型中存储 `NaN`、`Infinity` 或 `Infinity` 值。 +- 目前,向量数据类型不能存储双精度浮点数。未来版本将支持这一功能。 + +有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 + +## MySQL兼容性 + +向量数据类型只在 TiDB 中支持,MySQL 不支持。 + +## 其他信息 + +- [向量函数和操作](/tidb-cloud/vector-search-functions-and-operators.md) +- [向量搜索索引](/tidb-cloud/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..51f775feb78d --- /dev/null +++ b/vector-search-functions-and-operators.md @@ -0,0 +1,279 @@ +--- +title: 向量函数和操作 +summary: 本文介绍 TiDB 的向量相关函数和操作。 +--- + +# 向量函数和操作 + + +## 向量函数 + +[向量数据类型](/vector-search-data-types.md)具有以下函数: + +**向量距离函数:** + +| Function Name | Description | +| --------------------------------------------------------- | ---------------------------------------------------------------- | +| [VEC_L2_DISTANCE](#vec_l2_distance) | Calculates L2 distance (Euclidean distance) between two vectors | +| [VEC_COSINE_DISTANCE](#vec_cosine_distance) | Calculates the cosine distance between two vectors | +| [VEC_NEGATIVE_INNER_PRODUCT](#vec_negative_inner_product) | Calculates the negative of the inner product between two vectors | +| [VEC_L1_DISTANCE](#vec_l1_distance) | Calculates L1 distance (Manhattan distance) between two vectors | + +**其他向量函数:** + +| Function Name | Description | +| ------------------------------- | --------------------------------------------------- | +| [VEC_DIMS](#vec_dims) | Returns the dimension of a vector | +| [VEC_L2_NORM](#vec_l2_norm) | Calculates the L2 norm (Euclidean norm) of a vector | +| [VEC_FROM_TEXT](#vec_from_text) | Converts a string into a vector | +| [VEC_AS_TEXT](#vec_as_text) | Converts a vector into a string | + +## 扩展内置函数和运算符 + +扩展了以下内置函数和操作符,支持对[向量数据类型](/vector-search-data-types.md)进行操作。 + +**算术运算符:** + +| Name | Description | +| :-------------------------------------------------------------------------------------- | :--------------------------------------- | +| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | Vector element-wise addition operator | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | Vector element-wise subtraction operator | + +有关向量运算工作原理的更多信息,请参阅 [向量数据类型 | 运算](/vector-search-data-types.md#运算)。 + +**聚合函数(GROUP BY):** + +| Name | Description | +| :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | +| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | Return a count of the number of rows returned | +| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | Return the count of a number of different values | +| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | Return the maximum value | +| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | Return the minimum value | + +**比较函数与操作符:** + +| Name | Description | +| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | Check whether a value is within a range of values | +| [`COALESCE()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | Return the first non-NULL argument | +| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | Equal operator | +| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | NULL-safe equal to operator | +| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | Greater than operator | +| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | Greater than or equal operator | +| [`GREATEST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | Return the largest argument | +| [`IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | Check whether a value is within a set of values | +| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | NULL value test | +| [`ISNULL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | Test whether the argument is NULL | +| [`LEAST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | Return the smallest argument | +| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | Less than operator | +| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | Less than or equal operator | +| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | Check whether a value is not within a range of values | +| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | Not equal operator | +| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | Check whether a value is not within a set of values | + +For more information about how vectors are compared, see [Vector Data Type | Comparison](/tidb-cloud/vector-search-data-types.md#comparison). + +**控制流函数:** + +| Name | Description | +| :------------------------------------------------------------------------------------------------ | :--------------------------- | +| [`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | Case operator | +| [`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) | If/else construct | +| [`IFNULL()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | Null if/else construct | +| [`NULLIF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) | Return NULL if expr1 = expr2 | + +**转换函数:** + +| Name | Description | +| :------------------------------------------------------------------------------------------ | :----------------------------- | +| [`CAST()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) | Cast a value as a certain type | +| [`CONVERT()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | Cast a value as a certain type | + +有关如何使用 `CAST()` 的更多信息,请参阅 [向量数据类型 | 类型转换](/vector-search-data-types.md#类型转换)。 + +## 参考 + +### VEC_L2_DISTANCE + +```sql +VEC_L2_DISTANCE(vector1, vector2) +``` + +使用以下公式计算两个向量之间的 L2 距离(欧氏距离): + +$DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ + +两个向量的维度必须相同。否则将返回错误信息。 + +例如: + +```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) +``` + +使用以下公式计算两个向量之间的余弦距离: + +$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}}}}}}$ + +两个向量的维度必须相同。否则将返回错误信息。 + +例如: + +```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) +``` + +利用两个向量间内积的负值计算距离,公式如下: + +$DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ + +两个向量的维度必须相同。否则将返回错误信息。 + +例如: + +```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 距离(曼哈顿距离): + +$DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ + +两个向量的维度必须相同。否则将返回错误信息。 + +例如: + +```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 范数(欧几里得范数): + +$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-index.md b/vector-search-index.md new file mode 100644 index 000000000000..ce27238990b8 --- /dev/null +++ b/vector-search-index.md @@ -0,0 +1,270 @@ +--- +title: 向量搜索索引 +summary: 了解如何构建和使用向量搜索索引来加速 TiDB 中的 K-Nearest neighbors (KNN) 查询。 +--- + +# 向量搜索索引 + +K 近邻(KNN)搜索是为向量空间中的给定点寻找 K 个最近点的问题。解决这个问题最直接的方法是暴力搜索,即计算向量空间中所有点与参考点之间的距离。这种方法能保证完美的精确度,但在实际应用中通常速度太慢。因此,近邻搜索问题通常采用近似算法来解决。 + +在 TiDB 中,您可以创建并利用向量搜索索引来对具有[向量数据类型](/vector-search-data-types.md)的列进行近似近邻(ANN)搜索。通过使用向量搜索索引,向量搜索查询可在几毫秒内完成。 + +TiDB 目前支持以下向量搜索索引算法: + +- HNSW + +## 创建 HNSW 向量索引 + +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 索引性能良好,准确率相对较高(特定情况下大于 98%)。 + +要创建 HNSW 向量索引,请在创建表格时在[向量数据类型](/vector-search-data-types.md)列的注释中指定索引定义: + +```sql +CREATE TABLE vector_table_with_index ( + id INT PRIMARY KEY, doc TEXT, + embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" +); +``` + +> **Note:** +> +> 创建向量索引的语法可能会在今后的版本中发生变化。 + +创建向量索引时,必须通过 `distance=` 配置指定距离度量: + +- Cosine Distance: `COMMENT "hnsw(distance=cosine)"` +- L2 Distance: `COMMENT "hnsw(distance=l2)"` + +只能为固定维度的向量列(如 `VECTOR(3)`)创建向量索引。它不能为混合维度的向量列(如 `VECTOR`)创建,因为向量距离只能在具有相同维度的向量之间计算。 + +如果您使用的是编程语言 SDK 或 ORM,请参阅以下文档以创建向量索引: + +- Python: [TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) +- Python: [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) +- Python: [Peewee](/vector-search-integrate-with-peewee.md) +- Python: [Django](/vector-search-integrate-with-django-orm.md) + +创建向量索引时请注意以下限制。这些限制可能会在未来的版本中删除: + +- 向量索引暂不支持 L1 距离和内积。 + +- 只能在创建表时定义和创建向量索引。创建表后,不能使用 DDL 语句按需创建向量索引。也不能使用 DDL 语句删除向量索引。 + +## 使用向量索引 + +在 K 近邻搜索查询中,可以使用 “ORDER BY ... LIMIT ”形式来使用向量搜索索引。LIMIT "形式,如下所示: + +```sql +SELECT * +FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +LIMIT 10 +``` + +如果要在向量搜索中使用索引,则必须使用与创建向量索引时所定义的相同的距离度量。 + +## 使用带过滤器的向量索引 + +包含预过滤(使用 `WHERE` 子句)的查询不能使用向量索引,因为它们不是根据 SQL 语义查询 K 近邻。例如 + +```sql +-- Filter is performed before kNN, so Vector Index cannot be used: + +SELECT * FROM vec_table +WHERE category = "document" +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +以下是几种方法: + +**向量搜索后的后置过滤器:** 首先查询 K 最近的邻居,然后过滤掉不需要的结果: + +```sql +-- The filter is performed after kNN for these queries, so Vector Index can be used: + +SELECT * FROM +( + SELECT * FROM vec_table + ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') + LIMIT 5 +) t +WHERE category = "document"; + +-- Note that this query may return less than 5 results if some are filtered out. +``` + +**使用表格分区**: [表分区](/partitioned-table.md)内的查询可以充分利用向量索引。如果要执行相等筛选器,这将非常有用,因为相等筛选器可以变成访问指定分区。 + +例如: 假设您想查找与特定产品版本最接近的文档。 + +```sql +-- Filter is performed before kNN, so Vector Index cannot be used: +SELECT * FROM docs +WHERE ver = "v2.0" +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +与其使用 `WHERE` 子句编写查询,不如对表进行分区,然后使用 [`PARTITION` 关键字] 在[分区](/partitioned-table.md#partition-selection)内进行查询: + +```sql +CREATE TABLE docs ( + id INT, + ver VARCHAR(10), + doc TEXT, + embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" +) 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)。 + +## 检查是否使用了向量索引 + +使用[`EXPLAIN`](/sql-statements/sql-statement-explain.md)或[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md)语句检查该查询是否使用了向量索引。当 `annIndex:` 出现在 `TableFullScan` 执行程序的 `operator info` 列中时,表示该表扫描使用了向量索引。 + +**示例:使用向量索引** + +```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) +``` + +当无法使用向量索引时,在某些情况下会出现警告,以帮助您了解原因: + +```sql +-- Using a wrong distance metric: +[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 + +-- Using a wrong order: +[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) 语句包含关于如何在 “执行信息 ”列中使用向量索引的详细信息: + +```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}},...} | | ++-----+--------------------------------------------------------+-----+ +``` + +> **Note:** +> +> 执行信息为内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 + +一些重要字段的解释: + +- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个向量索引。 +- `vector_index.load.from_s3`: 从 S3 加载的索引数量。 +- `vector_index.load.from_disk`: 从磁盘加载的索引数量。该索引之前已从 S3 下载。 +- `vector_index.load.from_cache`: 从缓存加载的索引数量。该索引之前已从 S3 下载。 +- `vector_index.search.total`: 在索引中搜索的总时长。延迟大通常意味着索引是冷索引(以前从未访问过,或很久以前访问过),因此在索引中搜索时会产生大量 IO。该字段可能大于实际查询时间,因为可能会并行搜索多个向量索引。 +- `vector_index.search.discarded_nodes`: 在搜索过程中访问但丢弃的向量行数。搜索结果不会考虑这些被丢弃的向量。数值过大通常表示有许多因 UPDATE 或 DELETE 语句而导致的陈旧行。 + +请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [EXPLAIN Walkthrough](/explain-walkthrough.md) 以了解如何解释输出。 + +## 另见 + +- [提高向量搜索性能](/vector-search-improve-performance.md) +- [向量数据类型](/tidb-cloud/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..f6a93e269cc6 --- /dev/null +++ b/vector-search-integrate-with-django-orm.md @@ -0,0 +1,233 @@ +--- +title: TiDB 向量搜索与 Django ORM 相集成 +summary: 了解如何将 TiDB 向量搜索与 Django ORM 集成,以存储嵌入并执行语义搜索。 +--- + +# TiDB 向量搜索与 Django ORM 结合 + +本教程将指导您如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储嵌入和执行向量搜索查询。 + +## 准备 + +要实现本部分的内容,需要确保安装以下内容: + +- [Python 3.8 or higher](https://www.python.org/downloads/) +- [Git](https://git-scm.com/downloads) +- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 + +## 运行示例应用程序 + +您可以通过以下步骤快速了解如何将 TiDB 向量搜索与 Django ORM 集成。 + +### 步骤 1. clone仓库 + +将 `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.*`。次版本号不必相同。建议使用最新的次版本。 + +更多信息,请参阅 [django-tidb repository](https://github.com/pingcap/django-tidb)。 + +### 步骤 4. 配置环境变量 + +1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 + +2. 单击右上角的**连接**。此时将显示连接对话框。 + +3. 确保连接对话框中的配置符合您的运行环境。 + + - **Endpoint Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与环境相匹配 + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 + +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 + ``` + +### Step 5. 运行demo + +迁移数据库模式: + +```bash +python manage.py migrate +``` + +运行 Django 开发服务器: + +```bash +python manage.py runserver +``` + +打开浏览器,访问 `http://127.0.0.1:8000` 尝试演示应用程序。以下是可用的 API 路径: + +| API Path | Description | +| --------------------------------------- | ---------------------------------------- | +| `POST: /insert_documents` | Insert documents with embeddings. | +| `GET: /get_nearest_neighbors_documents` | Get the 3-nearest neighbor documents. | +| `GET: /get_documents_within_distance` | Get documents within a certain distance. | + +## 示例代码片段 + +您可以参考以下示例代码片段来完成自己的应用程序开发。 + +### 连接到 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 集群的实际值设置环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`。 + +### 创建向量表 + +#### 定义向量列 + +`tidb-django` 提供了一个 `VectorField` 来在表中存储向量嵌入。 + +创建一个表格,其中有一列名为 `embedding`,用于存储三维向量。 + +```python +class Document(models.Model): + content = models.TextField() + embedding = VectorField(dimensions=3) +``` + +#### 用索引定义优化的向量列 + +定义三维向量列,并使用[向量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 + +```python +class DocumentWithIndex(models.Model): + content = models.TextField() + # Note: + # - Using comment to add hnsw index is a temporary solution. In the future it will use `CREATE INDEX` syntax. + # - Currently the HNSW index cannot be changed after the table has been created. + # - Only Django >= 4.2 supports `db_comment`. + embedding = VectorField(dimensions=3, db_comment="hnsw(distance=cosine)") +``` + +TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 + +### 存储向量 + +```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` + +根据余弦距离函数,搜索与查询向量“[1, 2, 3]”语义最接近的前 3 个内容。 + +```python +results = Document.objects.annotate( + distance=CosineDistance('embedding', [1, 2, 3]) +).order_by('distance')[:3] +``` + +### 搜索一定距离内的向量 + +搜索与查询向量“[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] +``` + +## See also + +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量搜索索引](/tidb-cloud/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..a28da87e49de --- /dev/null +++ b/vector-search-integrate-with-peewee.md @@ -0,0 +1,223 @@ +--- +title: TiDB 向量搜索与 peewee 相结合 +summary: 了解如何将 TiDB 向量搜索与 peewee 集成,以存储嵌入信息并执行语义搜索。 +--- + +# TiDB 向量搜索与 peewee 结合 + +本教程将展示如何使用 [peewee](https://docs.peewee-orm.com/)与TiDB向量搜索交互、存储嵌入和执行向量搜索查询。 + +## 准备 + +要实现本部分的内容,需要确保安装以下内容: + +- [Python 3.8 or higher](https://www.python.org/downloads/) installed. +- [Git](https://git-scm.com/downloads) installed. +- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 + +## 运行示例应用程序 + +通过以下步骤,您可以快速了解如何将 TiDB 向量搜索与 peewee 结合。 + +### Step 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. 配置环境变量 + +1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 + +2. 单击右上角的**连接**。此时将显示连接对话框。 + +3. 确保连接对话框中的配置符合您的运行环境。 + + - **Endpoint Type** 设置为 `Public`. + - **Branch** 设置为 `main`. + - **Connect With** 设置为 `General`. + - **Operating System** 与环境相匹配. + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 + +5. In the root directory of your Python project, create a `.env` file and paste the connection parameters to the corresponding environment variables. + + - `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. 运行demo + +```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 +# # 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, +) +``` + +#### 定义向量列 + +创建一个表格,其中有一列名为 “peewee_demo_documents”,用于存储一个三维向量。 + +```python +class Document(Model): + class Meta: + database = db + table_name = 'peewee_demo_documents' + + content = TextField() + embedding = VectorField(3) +``` + +#### 用索引定义优化的矢量列 + +定义三维矢量列,并使用[向量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 + +```python +class DocumentWithIndex(Model): + class Meta: + database = db + table_name = 'peewee_demo_documents_with_index' + + content = TextField() + embedding = VectorField(3, constraints=[SQL("COMMENT 'hnsw(distance=cosine)'")]) +``` + +TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 + +### 存储向量 + +```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]) +``` + +### 搜索近邻向量 + +根据余弦距离函数,搜索与查询向量“[1, 2, 3]”语义最接近的前 3 个向量。 + +```python +distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') +results = Document.select(Document, distance).order_by(distance).limit(3) +``` + +### 搜索一定距离内的向量 + +搜索与查询向量`“`[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) +``` + +## See also + +- [向量数据类型](/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..0083019cae31 --- /dev/null +++ b/vector-search-integrate-with-sqlalchemy.md @@ -0,0 +1,196 @@ +--- +title: TiDB 向量搜索与 SQLAlchemy 结合 +summary: 了解如何将 TiDB 向量搜索与 SQLAlchemy 结合,以存储embedding并执行语义搜索。 +--- + +# TiDB 向量搜索与 SQLAlchemy 结合 + +本教程将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/)与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md)交互、存储嵌入和执行向量搜索查询。 + + +## Prerequisites + +要实现本部分的内容,需要确保安装以下内容: + +- [Python 3.8 or higher](https://www.python.org/downloads/) installed. +- [Git](https://git-scm.com/downloads) installed. +- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 + +## 运行示例应用程序 + +您可以通过以下步骤快速了解如何将 TiDB 向量搜索与 SQLAlchemy 结合。 + +### 步骤 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. 配置环境变量 + +1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 + +2. 单击右上角的**连接**。此时将显示连接对话框。 + +3. 确保连接对话框中的配置符合您的运行环境。 + + - **Endpoint Type** 设置为 `Public`. + - **Branch** 设置为 `main`. + - **Connect With** 设置为 `SQLAlchemy`. + - **Operating System** 与环境相匹配. + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + +4. 单击 **PyMySQL** 标签,复制连接字符串。 + + > **Tip:** + > + > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 + +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. 运行demo + +```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)) +``` + +#### 用索引定义优化的矢量列 + +定义三维矢量列,并使用[矢量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 + +```python +class DocumentWithIndex(Base): + __tablename__ = 'sqlalchemy_demo_documents_with_index' + id = Column(Integer, primary_key=True) + content = Column(Text) + embedding = Column(VectorType(3), comment="hnsw(distance=cosine)") +``` + +TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 + +### 存储带有向量的文档 + +```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() +``` + +### 搜索近邻向量 + +根据余弦距离函数,搜索与查询向量`[1, 2, 3]`”`语义最接近的前 3 篇向量。 + +```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() +``` + +### 搜索一定距离内的向量 + +搜索与查询向量`[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() +``` + +## See also + +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-limitations.md b/vector-search-limitations.md new file mode 100644 index 000000000000..0d3a07f563ac --- /dev/null +++ b/vector-search-limitations.md @@ -0,0 +1,21 @@ +--- +title: 向量搜索限制 +summary: 本文介绍 TiDB 的向量搜索限制。 +--- + +# 向量搜索限制 + +本文档描述了 TiDB 向量搜索的已知限制。我们将继续努力,通过添加更多功能来提升您的使用体验。 + +- 最大支持16383维[向量](/vector-search-data-types.md)。 + +- 向量数据仅支持单精度浮点数 (Float32)。 + +- 创建[向量索引](/vector-search-index.md)时只支持余弦距离和L2距离。 + +## 反馈 + +我们非常重视您的反馈意见,并随时准备提供帮助: + +- [Join our Discord](https://discord.gg/zcqexutz2R) +- [Visit our Support Portal](https://tidb.support.pingcap.com/) \ No newline at end of file From 0b31525821f25cf78515130b4e1e042afbe11776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 2 Sep 2024 13:50:37 +0800 Subject: [PATCH 002/109] remove vector index part MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 7 +- vector-search-index.md | 270 --------------------- vector-search-integrate-with-django-orm.md | 23 +- vector-search-integrate-with-peewee.md | 23 +- vector-search-integrate-with-sqlalchemy.md | 19 +- vector-search-limitations.md | 1 - 6 files changed, 9 insertions(+), 334 deletions(-) delete mode 100644 vector-search-index.md diff --git a/vector-search-data-types.md b/vector-search-data-types.md index f929188a26a9..937cef9b7440 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -14,7 +14,6 @@ TiDB 提供的矢量数据类型专门针对AI向量嵌入用例进行了优化 与存储在`JSON`列中相比,向量数据类型具有这些优势: -- 支持向量索引。 可以通过构建[向量搜索索引]()加速查询。 - 指定维度。可以指定一个维度,禁止插入不同维度的向量。 - 优化存储格式。向量数据类型的存储空间效率甚至比`JSON`数据类型更高。 @@ -55,7 +54,6 @@ ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3) 有关向量数据类型的可用函数和操作,参阅[向量函数与操作](/vector-search-functions-and-operators.md) -有关向量搜索索引的信息,参阅[向量搜索索引](/vector-search-index.md) ## 不同维度的向量 @@ -71,8 +69,6 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 dimensions vector, INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK ``` -但是,我们不能为此列构建[向量搜索索引](/vector-search-index.md),因为向量距离只能在具有相同维度的向量之间计算。 - ## 对比 我们可以使用[比较运算符](/vector-search-functions-and-operators.md)来比较两个向量,如:`=`, `!=`, `<`, `>`, `<=`, and `>=`。有关向量数据类型的比较运算符和函数的完整列表,参阅[向量函数与操作](/vector-search-functions-and-operators.md)。 @@ -244,5 +240,4 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 其他信息 -- [向量函数和操作](/tidb-cloud/vector-search-functions-and-operators.md) -- [向量搜索索引](/tidb-cloud/vector-search-index.md) \ No newline at end of file +- [向量函数和操作](/tidb-cloud/vector-search-functions-and-operators.md) \ No newline at end of file diff --git a/vector-search-index.md b/vector-search-index.md deleted file mode 100644 index ce27238990b8..000000000000 --- a/vector-search-index.md +++ /dev/null @@ -1,270 +0,0 @@ ---- -title: 向量搜索索引 -summary: 了解如何构建和使用向量搜索索引来加速 TiDB 中的 K-Nearest neighbors (KNN) 查询。 ---- - -# 向量搜索索引 - -K 近邻(KNN)搜索是为向量空间中的给定点寻找 K 个最近点的问题。解决这个问题最直接的方法是暴力搜索,即计算向量空间中所有点与参考点之间的距离。这种方法能保证完美的精确度,但在实际应用中通常速度太慢。因此,近邻搜索问题通常采用近似算法来解决。 - -在 TiDB 中,您可以创建并利用向量搜索索引来对具有[向量数据类型](/vector-search-data-types.md)的列进行近似近邻(ANN)搜索。通过使用向量搜索索引,向量搜索查询可在几毫秒内完成。 - -TiDB 目前支持以下向量搜索索引算法: - -- HNSW - -## 创建 HNSW 向量索引 - -[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 索引性能良好,准确率相对较高(特定情况下大于 98%)。 - -要创建 HNSW 向量索引,请在创建表格时在[向量数据类型](/vector-search-data-types.md)列的注释中指定索引定义: - -```sql -CREATE TABLE vector_table_with_index ( - id INT PRIMARY KEY, doc TEXT, - embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" -); -``` - -> **Note:** -> -> 创建向量索引的语法可能会在今后的版本中发生变化。 - -创建向量索引时,必须通过 `distance=` 配置指定距离度量: - -- Cosine Distance: `COMMENT "hnsw(distance=cosine)"` -- L2 Distance: `COMMENT "hnsw(distance=l2)"` - -只能为固定维度的向量列(如 `VECTOR(3)`)创建向量索引。它不能为混合维度的向量列(如 `VECTOR`)创建,因为向量距离只能在具有相同维度的向量之间计算。 - -如果您使用的是编程语言 SDK 或 ORM,请参阅以下文档以创建向量索引: - -- Python: [TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) -- Python: [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) -- Python: [Peewee](/vector-search-integrate-with-peewee.md) -- Python: [Django](/vector-search-integrate-with-django-orm.md) - -创建向量索引时请注意以下限制。这些限制可能会在未来的版本中删除: - -- 向量索引暂不支持 L1 距离和内积。 - -- 只能在创建表时定义和创建向量索引。创建表后,不能使用 DDL 语句按需创建向量索引。也不能使用 DDL 语句删除向量索引。 - -## 使用向量索引 - -在 K 近邻搜索查询中,可以使用 “ORDER BY ... LIMIT ”形式来使用向量搜索索引。LIMIT "形式,如下所示: - -```sql -SELECT * -FROM vector_table_with_index -ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') -LIMIT 10 -``` - -如果要在向量搜索中使用索引,则必须使用与创建向量索引时所定义的相同的距离度量。 - -## 使用带过滤器的向量索引 - -包含预过滤(使用 `WHERE` 子句)的查询不能使用向量索引,因为它们不是根据 SQL 语义查询 K 近邻。例如 - -```sql --- Filter is performed before kNN, so Vector Index cannot be used: - -SELECT * FROM vec_table -WHERE category = "document" -ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') -LIMIT 5; -``` - -以下是几种方法: - -**向量搜索后的后置过滤器:** 首先查询 K 最近的邻居,然后过滤掉不需要的结果: - -```sql --- The filter is performed after kNN for these queries, so Vector Index can be used: - -SELECT * FROM -( - SELECT * FROM vec_table - ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') - LIMIT 5 -) t -WHERE category = "document"; - --- Note that this query may return less than 5 results if some are filtered out. -``` - -**使用表格分区**: [表分区](/partitioned-table.md)内的查询可以充分利用向量索引。如果要执行相等筛选器,这将非常有用,因为相等筛选器可以变成访问指定分区。 - -例如: 假设您想查找与特定产品版本最接近的文档。 - -```sql --- Filter is performed before kNN, so Vector Index cannot be used: -SELECT * FROM docs -WHERE ver = "v2.0" -ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') -LIMIT 5; -``` - -与其使用 `WHERE` 子句编写查询,不如对表进行分区,然后使用 [`PARTITION` 关键字] 在[分区](/partitioned-table.md#partition-selection)内进行查询: - -```sql -CREATE TABLE docs ( - id INT, - ver VARCHAR(10), - doc TEXT, - embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" -) 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)。 - -## 检查是否使用了向量索引 - -使用[`EXPLAIN`](/sql-statements/sql-statement-explain.md)或[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md)语句检查该查询是否使用了向量索引。当 `annIndex:` 出现在 `TableFullScan` 执行程序的 `operator info` 列中时,表示该表扫描使用了向量索引。 - -**示例:使用向量索引** - -```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) -``` - -当无法使用向量索引时,在某些情况下会出现警告,以帮助您了解原因: - -```sql --- Using a wrong distance metric: -[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 - --- Using a wrong order: -[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) 语句包含关于如何在 “执行信息 ”列中使用向量索引的详细信息: - -```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}},...} | | -+-----+--------------------------------------------------------+-----+ -``` - -> **Note:** -> -> 执行信息为内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 - -一些重要字段的解释: - -- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个向量索引。 -- `vector_index.load.from_s3`: 从 S3 加载的索引数量。 -- `vector_index.load.from_disk`: 从磁盘加载的索引数量。该索引之前已从 S3 下载。 -- `vector_index.load.from_cache`: 从缓存加载的索引数量。该索引之前已从 S3 下载。 -- `vector_index.search.total`: 在索引中搜索的总时长。延迟大通常意味着索引是冷索引(以前从未访问过,或很久以前访问过),因此在索引中搜索时会产生大量 IO。该字段可能大于实际查询时间,因为可能会并行搜索多个向量索引。 -- `vector_index.search.discarded_nodes`: 在搜索过程中访问但丢弃的向量行数。搜索结果不会考虑这些被丢弃的向量。数值过大通常表示有许多因 UPDATE 或 DELETE 语句而导致的陈旧行。 - -请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [EXPLAIN Walkthrough](/explain-walkthrough.md) 以了解如何解释输出。 - -## 另见 - -- [提高向量搜索性能](/vector-search-improve-performance.md) -- [向量数据类型](/tidb-cloud/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 index f6a93e269cc6..fe4cea2a551d 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -5,7 +5,7 @@ summary: 了解如何将 TiDB 向量搜索与 Django ORM 集成,以存储嵌 # TiDB 向量搜索与 Django ORM 结合 -本教程将指导您如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储嵌入和执行向量搜索查询。 +本教程将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储嵌入和执行向量搜索查询。 ## 准备 @@ -176,23 +176,7 @@ class Document(models.Model): embedding = VectorField(dimensions=3) ``` -#### 用索引定义优化的向量列 - -定义三维向量列,并使用[向量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 - -```python -class DocumentWithIndex(models.Model): - content = models.TextField() - # Note: - # - Using comment to add hnsw index is a temporary solution. In the future it will use `CREATE INDEX` syntax. - # - Currently the HNSW index cannot be changed after the table has been created. - # - Only Django >= 4.2 supports `db_comment`. - embedding = VectorField(dimensions=3, db_comment="hnsw(distance=cosine)") -``` - -TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 - -### 存储向量 +### 存储带有向量的文档 ```python Document.objects.create(content="dog", embedding=[1, 2, 1]) @@ -229,5 +213,4 @@ results = Document.objects.annotate( ## See also -- [向量数据类型](/tidb-cloud/vector-search-data-types.md) -- [向量搜索索引](/tidb-cloud/vector-search-index.md) \ No newline at end of file +- [向量数据类型](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index a28da87e49de..f602f97ba9da 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -121,7 +121,7 @@ Get documents within a certain distance: 您可以参考以下示例代码片段来开发您的应用程序。 -### 创建矢量表 +### 创建向量表 #### 连接至 TiDB 集群 @@ -174,23 +174,7 @@ class Document(Model): embedding = VectorField(3) ``` -#### 用索引定义优化的矢量列 - -定义三维矢量列,并使用[向量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 - -```python -class DocumentWithIndex(Model): - class Meta: - database = db - table_name = 'peewee_demo_documents_with_index' - - content = TextField() - embedding = VectorField(3, constraints=[SQL("COMMENT 'hnsw(distance=cosine)'")]) -``` - -TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 - -### 存储向量 +### 存储带有向量的文档 ```python Document.create(content='dog', embedding=[1, 2, 1]) @@ -219,5 +203,4 @@ results = Document.select(Document, distance).where(distance_expression < 0.2).o ## See also -- [向量数据类型](/vector-search-data-types.md) -- [向量搜索索引](/vector-search-index.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 0083019cae31..032002864c8b 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -110,7 +110,7 @@ Get documents within a certain distance: 您可以参考以下示例代码片段来开发您的应用程序。 -### 创建矢量表 +### 创建向量表 #### 连接至 TiDB 集群 @@ -142,20 +142,6 @@ class Document(Base): embedding = Column(VectorType(3)) ``` -#### 用索引定义优化的矢量列 - -定义三维矢量列,并使用[矢量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 - -```python -class DocumentWithIndex(Base): - __tablename__ = 'sqlalchemy_demo_documents_with_index' - id = Column(Integer, primary_key=True) - content = Column(Text) - embedding = Column(VectorType(3), comment="hnsw(distance=cosine)") -``` - -TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 - ### 存储带有向量的文档 ```python @@ -192,5 +178,4 @@ with Session(engine) as session: ## See also -- [向量数据类型](/vector-search-data-types.md) -- [向量搜索索引](/vector-search-index.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 0d3a07f563ac..a01b6811b3e3 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -11,7 +11,6 @@ summary: 本文介绍 TiDB 的向量搜索限制。 - 向量数据仅支持单精度浮点数 (Float32)。 -- 创建[向量索引](/vector-search-index.md)时只支持余弦距离和L2距离。 ## 反馈 From 96f270153e32dcd2d6bb2436953a462075354974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 2 Sep 2024 18:45:32 +0800 Subject: [PATCH 003/109] modify cluster type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- media/vector-search/embedding-search.png | Bin 0 -> 162978 bytes vector-search-data-types.md | 36 ++--- vector-search-functions-and-operators.md | 74 ++++----- vector-search-get-started-using-python.md | 177 +++++++++++++++++++++ vector-search-get-started-using-sql | 135 ++++++++++++++++ vector-search-integrate-with-django-orm.md | 47 ++---- vector-search-integrate-with-peewee.md | 39 ++--- vector-search-integrate-with-sqlalchemy.md | 42 ++--- vector-search-overview.md | 62 ++++++++ views.md | 2 +- 10 files changed, 466 insertions(+), 148 deletions(-) create mode 100644 media/vector-search/embedding-search.png create mode 100644 vector-search-get-started-using-python.md create mode 100644 vector-search-get-started-using-sql create mode 100644 vector-search-overview.md diff --git a/media/vector-search/embedding-search.png b/media/vector-search/embedding-search.png new file mode 100644 index 0000000000000000000000000000000000000000..0035ada1b7479ed307ccfae46762315f3e2123a7 GIT binary patch literal 162978 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 INSERT INTO vector_table VALUES (4, '[0.3, 0.5]'); @@ -82,7 +82,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, 不同维度的向量采用字典序比较,具有一下特性: -- 两个矢量逐个元素进行比较,每个元素都以数值形式进行比较。 +- 两个向量逐个元素进行比较,每个元素都以数值形式进行比较。 - 第一个不匹配的元素决定哪一个向量在字典序上 _less_ 或 _greater_。 - 如果一个向量是另一个向量的前缀,那么较短的向量为 _less_ 。 - 长度相同、元素相同的两个向量为 _equal_ 。 @@ -97,7 +97,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, 在比较向量常量时,需要考虑执行从字符串到向量的 [显式转换](#cast),以避免基于字符串值的比较: ```sql --- Because string is given, TiDB is comparing strings: +-- 因为给出了字符串,所以 TiDB 会比较字符串 [tidb]> SELECT '[12.0]' < '[4.0]'; +--------------------+ | '[12.0]' < '[4.0]' | @@ -106,7 +106,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, +--------------------+ 1 row in set (0.01 sec) --- Cast to vector explicitly to compare by vectors: +-- 显式转换为向量,以便通过向量进行比较: [tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); +--------------------------------------------------+ | VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | @@ -157,7 +157,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 在调用接收向量数据类型的函数时,存在隐式转换: ```sql --- There is an implicit cast here, since VEC_DIMS only accepts VECTOR arguments: +-- 由于 VEC_DIMS 只接受 VECTOR 参数,因此这里有一个隐式转换: [tidb]> SELECT VEC_DIMS('[0.3, 0.5, -0.1]'); +------------------------------+ | VEC_DIMS('[0.3, 0.5, -0.1]') | @@ -166,7 +166,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +------------------------------+ 1 row in set (0.01 sec) --- Cast explicitly using VEC_FROM_TEXT: +-- 使用 VEC_FROM_TEXT 进行显式转存: [tidb]> SELECT VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')); +---------------------------------------------+ | VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')) | @@ -175,7 +175,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +---------------------------------------------+ 1 row in set (0.01 sec) --- Cast explicitly using CAST(... AS VECTOR): +-- 使用 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)) | @@ -188,7 +188,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 当运算符或函数接受多种数据类型时,请使用显式转换。例如,在比较中,使用显式转换来比较向量数值而不是字符串数值: ```sql --- Because string is given, TiDB is comparing strings: +-- 因为给出了字符串,所以 TiDB 会比较字符串: [tidb]> SELECT '[12.0]' < '[4.0]'; +--------------------+ | '[12.0]' < '[4.0]' | @@ -197,7 +197,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +--------------------+ 1 row in set (0.01 sec) --- Cast to vector explicitly to compare by vectors: +-- 显式转换为向量,以便通过向量进行比较: [tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]'); +--------------------------------------------------+ | VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') | @@ -207,10 +207,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -要显式地将向量转换为字符串表示,请使用`VEC_AS_TEXT()`函数: +要显式地将向量转换为字符串表示,请使用 `VEC_AS_TEXT()` 函数: ```sql --- String representation is normalized: +-- 规范化表示字符串: [tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); +--------------------------------------+ | VEC_AS_TEXT('[0.3, 0.5, -0.1]') | @@ -234,10 +234,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 -## MySQL兼容性 +## MySQL 兼容性 向量数据类型只在 TiDB 中支持,MySQL 不支持。 -## 其他信息 +## 另请参阅 - [向量函数和操作](/tidb-cloud/vector-search-functions-and-operators.md) \ No newline at end of file diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 51f775feb78d..a9ddf114f79a 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -12,21 +12,21 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 **向量距离函数:** -| Function Name | Description | -| --------------------------------------------------------- | ---------------------------------------------------------------- | -| [VEC_L2_DISTANCE](#vec_l2_distance) | Calculates L2 distance (Euclidean distance) between two vectors | -| [VEC_COSINE_DISTANCE](#vec_cosine_distance) | Calculates the cosine distance between two vectors | -| [VEC_NEGATIVE_INNER_PRODUCT](#vec_negative_inner_product) | Calculates the negative of the inner product between two vectors | -| [VEC_L1_DISTANCE](#vec_l1_distance) | Calculates L1 distance (Manhattan distance) between two vectors | +| Function Name | Description | +| --------------------------------------------------------- | ----------------------------------------------------------- | +| [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 距离(曼哈顿距离) | **其他向量函数:** | Function Name | Description | | ------------------------------- | --------------------------------------------------- | -| [VEC_DIMS](#vec_dims) | Returns the dimension of a vector | -| [VEC_L2_NORM](#vec_l2_norm) | Calculates the L2 norm (Euclidean norm) of a vector | -| [VEC_FROM_TEXT](#vec_from_text) | Converts a string into a vector | -| [VEC_AS_TEXT](#vec_as_text) | Converts a vector into a string | +| [VEC_DIMS](#vec_dims) | 返回一个 vector | +| [VEC_L2_NORM](#vec_l2_norm) | 计算向量的 L2 规范(欧氏规范 | +| [VEC_FROM_TEXT](#vec_from_text) | 将字符串转换为向量 | +| [VEC_AS_TEXT](#vec_as_text) | 将向量转换为字符串 | ## 扩展内置函数和运算符 @@ -36,8 +36,8 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 | Name | Description | | :-------------------------------------------------------------------------------------- | :--------------------------------------- | -| [`+`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_plus) | Vector element-wise addition operator | -| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | Vector element-wise subtraction operator | +| [`+`](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#运算)。 @@ -45,33 +45,33 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 | Name | Description | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | -| [`COUNT()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count) | Return a count of the number of rows returned | -| [`COUNT(DISTINCT)`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct) | Return the count of a number of different values | -| [`MAX()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max) | Return the maximum value | -| [`MIN()`](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min) | Return the minimum value | +| [`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) | 返回最小值 | **比较函数与操作符:** | Name | Description | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -| [`BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_between) | Check whether a value is within a range of values | -| [`COALESCE()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce) | Return the first non-NULL argument | -| [`=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal) | Equal operator | -| [`<=>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to) | NULL-safe equal to operator | -| [`>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than) | Greater than operator | -| [`>=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_greater-than-or-equal) | Greater than or equal operator | -| [`GREATEST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_greatest) | Return the largest argument | -| [`IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in) | Check whether a value is within a set of values | -| [`IS NULL`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_is-null) | NULL value test | -| [`ISNULL()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_isnull) | Test whether the argument is NULL | -| [`LEAST()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_least) | Return the smallest argument | -| [`<`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than) | Less than operator | -| [`<=`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than-or-equal) | Less than or equal operator | -| [`NOT BETWEEN ... AND ...`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-between) | Check whether a value is not within a range of values | -| [`!=`, `<>`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-equal) | Not equal operator | -| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | Check whether a value is not within a set of values | - -For more information about how vectors are compared, see [Vector Data Type | Comparison](/tidb-cloud/vector-search-data-types.md#comparison). +| [`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) | 返回第一个非空参数 | +| [`=`](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) | 安全的等于运算符 | +| [`>`](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#comparison)。 **控制流函数:** @@ -86,8 +86,8 @@ For more information about how vectors are compared, see [Vector Data Type | Com | Name | Description | | :------------------------------------------------------------------------------------------ | :----------------------------- | -| [`CAST()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast) | Cast a value as a certain type | -| [`CONVERT()`](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | Cast a value as a certain type | +| [`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#类型转换)。 @@ -274,6 +274,6 @@ VEC_AS_TEXT(vector) 向量函数以及内置函数和向量数据类型运算符的扩展用法是 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..8ccad050d001 --- /dev/null +++ b/vector-search-get-started-using-python.md @@ -0,0 +1,177 @@ +--- +title: 使用Python开始向量搜索 +summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语义搜索的人工智能应用程序。 +--- + +# 使用 Python 开始向量搜索 + +本教程演示如何开发一个简单的人工智能应用程序,提供**语义搜索**功能。与传统的关键字搜索不同,语义搜索可以智能地理解您的查询背后的含义。例如,如果您有标题为 “狗”、“鱼 ”和 “树 ”的文档,而您搜索的是 “一种会游泳的动物”,那么应用程序会将 “鱼 ”识别为最相关的结果。 + +在本教程中,您将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和人工智能模型开发此人工智能应用程序。 + + +## 准备 + +在开始之前,您需要确保以下内容正确安装: + +- [Python 3.8 or higher](https://www.python.org/downloads/) +- [Git](https://git-scm.com/downloads) +- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +## 开始 + +要直接运行演示,请查看 [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#vector-embedding)。 + +### 步骤 3. 配置 TiDB 群集的连接字符串 + +在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + + - `HOST`: TiDB 集群的主机。 + - `PORT`: TiDB 集群的端口。 + - `USERNAME`: 连接 TiDB 集群的用户名。 + - `PASSWORD`: 连接 TiDB 集群的密码。 + - `DATABASE`: 要连接的数据库名称。 + - `CA_PATH`: 根证书文件的路径。 + + 以下是 MacOS 的示例: + + ```dotenv + TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + ``` + +### 步骤 4. 初始化嵌入模型 + +[嵌入模型](/vector-search-overview.md#embedding-model) 将数据转换为[向量嵌入](/vector-search-overview.md#vector-embedding)。本示例使用预训练模型 [**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 个维度。 + +```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. 嵌入文本数据并存储向量 + +在这一步中,您将准备包含单词的示例文档,如 “狗”、“鱼 ”和 “树”。以下代码使用 `text_to_embedding()` 函数将这些文本文档转换为向量嵌入,然后将它们插入向量存储区。 + +```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. 执行语义搜索 + +在这一步中,您将搜索 “一种会游泳的动物”,它与现有文档中的任何单词都不直接匹配。 + +下面的代码会再次使用 `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 +``` + +从输出结果来看,会游泳的动物很可能是一条鱼,或者是一只有游泳天赋的狗。 + +该演示展示了向量搜索如何高效地找到最相关的文档,搜索结果按向量的远近排列:距离越小,文档越相关。 + +## 另请参阅 + +- [Vector Data Types](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-get-started-using-sql b/vector-search-get-started-using-sql new file mode 100644 index 000000000000..b9df79aa5d68 --- /dev/null +++ b/vector-search-get-started-using-sql @@ -0,0 +1,135 @@ +--- +title: 使用SQL开始向量搜索 +summary: 了解如何使用 SQL 语句快速开始使用 TiDB Cloud 中的向量搜索,并为生成式人工智能应用提供动力。 +--- + +# 使用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 集群。 +- 创建向量表 +- 存储向量嵌入 +- 执行向量搜索查询 + +## 准备 + +在使用向量搜索之前,您需要确认: + +- 安装了 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 +- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +## 开始 + +### 步骤 1. 连接到 TiDB 集群 + +复制连接命令并将其粘贴到终端。以下是 macOS 的示例: + + ```bash + mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' + ``` + +### 步骤 2. 创建向量表 + +有了向量搜索支持,您就可以使用 `VECTOR` 类型列在 TiDB 中存储 [向量嵌入](/vector-search-overview.md#vector-embedding)。 + +要创建带有三维 `VECTOR` 列的表,请使用 MySQL CLI 执行以下 SQL 语句: + +```sql +USE test; +CREATE TABLE embedded_documents ( + id INT PRIMARY KEY, + -- 存储文档的原始内容。 + document TEXT, + -- 存储文件的向量表示。 + embedding VECTOR(3) +); +``` + +预期输出如下 + +```text +Query OK, 0 rows affected (0.27 sec) +``` + +### 步骤 3. 存储向量嵌入 + +将三行数据及其 [向量嵌入](/vector-search-overview.md#vector-embedding) 插入 `embedded_documents` 表: + +```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#embedding-model) 通常会产生数百或数千维的向量嵌入。 + +### 步骤 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]`。在实际应用中,需要使用嵌入模型将用户的搜索词转换为向量嵌入。 + +执行以下 SQL 语句后,TiDB 将通过计算和排序向量嵌入之间的余弦距离(`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) +``` + +从输出结果来看,会游泳的动物很可能是一条鱼,或者是一只有游泳天赋的狗。 + +## 另请参阅 + +- [向量数据类型](/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 index fe4cea2a551d..43e275896688 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -1,6 +1,6 @@ --- -title: TiDB 向量搜索与 Django ORM 相集成 -summary: 了解如何将 TiDB 向量搜索与 Django ORM 集成,以存储嵌入并执行语义搜索。 +title: TiDB 向量搜索与 Django ORM 结合 +summary: 了解如何将 TiDB 向量搜索与 Django ORM 结合,以存储嵌入并执行语义搜索。 --- # TiDB 向量搜索与 Django ORM 结合 @@ -13,13 +13,13 @@ summary: 了解如何将 TiDB 向量搜索与 Django ORM 集成,以存储嵌 - [Python 3.8 or higher](https://www.python.org/downloads/) - [Git](https://git-scm.com/downloads) -- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 +- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 您可以通过以下步骤快速了解如何将 TiDB 向量搜索与 Django ORM 集成。 -### 步骤 1. clone仓库 +### 步骤 1. 克隆仓库 将 `tidb-vector-python` 仓库克隆到本地: @@ -55,36 +55,15 @@ pip install Django django-tidb mysqlclient numpy python-dotenv #### 什么是 `django-tidb`? -`django-tidb`使用django框架提供了与tidb交互的示例,它实现了 Django ORM 以支持 TiDB 特有的功能(例如,向量搜索),并解决了 TiDB 和 Django 之间的兼容性问题。 +`django-tidb`使用django框架提供了与tidb交互的示例,它实现了 Django ORM 以支持 TiDB 的向量搜索,并解决了 TiDB 和 Django 之间的兼容性问题。 -要安装 `django-tidb`,请选择与 Django 版本相匹配的版本。例如,如果使用的是 `django==4.2.*`, 则安装 `django-tidb===4.2.*`。次版本号不必相同。建议使用最新的次版本。 +要安装 `django-tidb`,请选择与 Django 版本相匹配的版本。例如,如果使用的是 `django==4.2.*`, 则安装 `django-tidb===4.2.*`。次版本号不必相同,但建议使用最新的次版本。 更多信息,请参阅 [django-tidb repository](https://github.com/pingcap/django-tidb)。 ### 步骤 4. 配置环境变量 -1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 - -2. 单击右上角的**连接**。此时将显示连接对话框。 - -3. 确保连接对话框中的配置符合您的运行环境。 - - - **Endpoint Type** 设置为 `Public` - - **Branch** 设置为 `main` - - **Connect With** 设置为 `General` - - **Operating System** 与环境相匹配 - - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 - -4. 从连接对话框中复制连接参数。 - - > **Tip:** - > - > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 - -5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 +在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - `TIDB_HOST`: TiDB 集群的主机。 - `TIDB_PORT`: TiDB 集群的端口。 @@ -96,7 +75,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv 以下是 MacOS 的示例: ```dotenv - TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_HOST=127.0.0.1 TIDB_PORT=4000 TIDB_USERNAME=********.root TIDB_PASSWORD=******** @@ -104,7 +83,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv TIDB_CA_PATH=/etc/ssl/cert.pem ``` -### Step 5. 运行demo +### Step 5. 运行 demo 迁移数据库模式: @@ -168,7 +147,7 @@ if TIDB_CA_PATH: `tidb-django` 提供了一个 `VectorField` 来在表中存储向量嵌入。 -创建一个表格,其中有一列名为 `embedding`,用于存储三维向量。 +创建一个表格,其中有一列名为 `embedding` ,用于存储三维向量。 ```python class Document(models.Model): @@ -193,7 +172,7 @@ TiDB 向量支持以下距离函数: - `CosineDistance` - `NegativeInnerProduct` -根据余弦距离函数,搜索与查询向量“[1, 2, 3]”语义最接近的前 3 个内容。 +根据余弦距离函数,搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 ```python results = Document.objects.annotate( @@ -203,7 +182,7 @@ results = Document.objects.annotate( ### 搜索一定距离内的向量 -搜索与查询向量“[1, 2, 3]”的余弦距离小于 0.2 的向量。 +搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python results = Document.objects.annotate( @@ -211,6 +190,6 @@ results = Document.objects.annotate( ).filter(distance__lt=0.2).order_by('distance')[:3] ``` -## See also +## 另请参阅 - [向量数据类型](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index f602f97ba9da..5764ffc49d8d 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -5,7 +5,7 @@ summary: 了解如何将 TiDB 向量搜索与 peewee 集成,以存储嵌入信 # TiDB 向量搜索与 peewee 结合 -本教程将展示如何使用 [peewee](https://docs.peewee-orm.com/)与TiDB向量搜索交互、存储嵌入和执行向量搜索查询。 +本教程将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 TiDB 向量搜索交互、存储嵌入和执行向量搜索查询。 ## 准备 @@ -13,7 +13,7 @@ summary: 了解如何将 TiDB 向量搜索与 peewee 集成,以存储嵌入信 - [Python 3.8 or higher](https://www.python.org/downloads/) installed. - [Git](https://git-scm.com/downloads) installed. -- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 +- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 @@ -53,28 +53,7 @@ pip install peewee pymysql python-dotenv tidb-vector ### 步骤 4. 配置环境变量 -1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 - -2. 单击右上角的**连接**。此时将显示连接对话框。 - -3. 确保连接对话框中的配置符合您的运行环境。 - - - **Endpoint Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `General`. - - **Operating System** 与环境相匹配. - - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 - -4. 从连接对话框中复制连接参数。 - - > **Tip:** - > - > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 - -5. In the root directory of your Python project, create a `.env` file and paste the connection parameters to the corresponding environment variables. +在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - `TIDB_HOST`: TiDB 集群的主机。 - `TIDB_PORT`: TiDB 集群的端口。 @@ -86,7 +65,7 @@ pip install peewee pymysql python-dotenv tidb-vector 以下是 MacOS 的示例: ```dotenv - TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com + TIDB_HOST=127.0.0.1 TIDB_PORT=4000 TIDB_USERNAME=********.root TIDB_PASSWORD=******** @@ -94,7 +73,7 @@ pip install peewee pymysql python-dotenv tidb-vector TIDB_CA_PATH=/etc/ssl/cert.pem ``` -### 步骤 5. 运行demo +### 步骤 5. 运行 demo ```bash python peewee-quickstart.py @@ -162,7 +141,7 @@ db = MySQLDatabase( #### 定义向量列 -创建一个表格,其中有一列名为 “peewee_demo_documents”,用于存储一个三维向量。 +创建一个表格,其中有一列名为 `peewee_demo_documents`,用于存储一个三维向量。 ```python class Document(Model): @@ -184,7 +163,7 @@ Document.create(content='tree', embedding=[1, 0, 0]) ### 搜索近邻向量 -根据余弦距离函数,搜索与查询向量“[1, 2, 3]”语义最接近的前 3 个向量。 +根据余弦距离函数,搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个向量。 ```python distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') @@ -193,7 +172,7 @@ results = Document.select(Document, distance).order_by(distance).limit(3) ### 搜索一定距离内的向量 -搜索与查询向量`“`[1, 2, 3]`的余弦距离小于 0.2 的文档。 +搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的文档。 ```python distance_expression = Document.embedding.cosine_distance([1, 2, 3]) @@ -201,6 +180,6 @@ distance = distance_expression.alias('distance') results = Document.select(Document, distance).where(distance_expression < 0.2).order_by(distance).limit(3) ``` -## See also +## 另请参阅 - [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 032002864c8b..a044e6696202 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -5,16 +5,16 @@ summary: 了解如何将 TiDB 向量搜索与 SQLAlchemy 结合,以存储embed # TiDB 向量搜索与 SQLAlchemy 结合 -本教程将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/)与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md)交互、存储嵌入和执行向量搜索查询。 +本教程将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md) 交互、存储嵌入和执行向量搜索查询。 -## Prerequisites +## 准备 要实现本部分的内容,需要确保安装以下内容: -- [Python 3.8 or higher](https://www.python.org/downloads/) installed. -- [Git](https://git-scm.com/downloads) installed. -- TiDB serverless集群。如果没有,请按照[使用 TiDB Serverless 构建 TiDB 集群](/develop/dev-guide-build-cluster-in-cloud.md)创建自己的 TiDB 集群。 +- [Python 3.8 or higher](https://www.python.org/downloads/) +- [Git](https://git-scm.com/downloads) +- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 @@ -54,33 +54,19 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector ### 步骤 4. 配置环境变量 -1. 导航至 [** 群集**](https://tidbcloud.com/console/clusters) 页面,然后单击目标群集的名称进入其概览页面。 +在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 -2. 单击右上角的**连接**。此时将显示连接对话框。 - -3. 确保连接对话框中的配置符合您的运行环境。 - - - **Endpoint Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `SQLAlchemy`. - - **Operating System** 与环境相匹配. - - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 - -4. 单击 **PyMySQL** 标签,复制连接字符串。 - - > **Tip:** - > - > 如果尚未设置密码,请单击**生成密码**生成一个随机密码。 - -5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接字符串粘贴到其中。 + - `HOST`: TiDB 集群的主机。 + - `PORT`: TiDB 集群的端口。 + - `USERNAME`: 连接 TiDB 集群的用户名。 + - `PASSWORD`: 连接 TiDB 集群的密码。 + - `DATABASE`: 要连接的数据库名称。 + - `CA`: 根证书文件的路径。 以下是 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" + TIDB_DATABASE_URL="mysql+pymysql://.root:@127.0.0.1:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" ``` ### 步骤 5. 运行demo @@ -176,6 +162,6 @@ with Session(engine) as session: ).filter(distance < 0.2).order_by(distance).limit(3).all() ``` -## See also +## 另请参阅 - [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-overview.md b/vector-search-overview.md new file mode 100644 index 000000000000..d8800a6d3103 --- /dev/null +++ b/vector-search-overview.md @@ -0,0 +1,62 @@ +--- +title: 向量搜索概述 +summary: 了解 TiDB 中的向量搜索。该功能提供了一种高效的搜索解决方案,可跨文档、图像、音频和视频等各种数据类型执行语义相似性搜索。 +--- + +# 向量搜索概述 + +TiDB 向量搜索提供了一种高效的搜索解决方案,可在各种数据类型(包括文档、图像、音频和视频)中执行语义相似性搜索。该功能使开发人员能够使用熟悉的 MySQL 技能,轻松构建具有生成人工智能(AI)功能的可扩展应用程序。 + + +## 概念 + +向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。这不同于传统的全文搜索,后者主要依赖于精确的关键词匹配和词频。 + +例如,全文搜索 “一种会游泳的动物” 只会返回包含这些精确关键词的结果。相比之下,向量搜索可以返回其他游泳动物的结果,如鱼或鸭子,即使没有准确的关键字。 + +### 向量嵌入 + +向量嵌入(vector embedding)又称嵌入(embedding),是在高维空间中表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的含义和上下文。 + +向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 + +TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化向量嵌入的存储和检索,增强其在人工智能领域的应用。您可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询以查找最相关的数据。 + +### 嵌入模型 + +嵌入模型是将数据转换为[向量嵌入](#vector-embedding)的算法。 + +选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,您可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 + +要了解如何为特定数据类型生成向量嵌入,请参阅嵌入提供程序集成教程或示例。 + +## 向量搜索如何工作 + +将原始数据转换为向量嵌入并存储在 TiDB 中后,您的应用程序就可以执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 + +TiDB Cloud 中的向量搜索(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 diff --git a/views.md b/views.md index 7329db7fe692..7ca98aaf0752 100644 --- a/views.md +++ b/views.md @@ -239,7 +239,7 @@ Query OK, 0 rows affected (0.02 sec) - TiDB 中视图为只读视图,不支持对视图进行 `UPDATE`、`INSERT`、`DELETE`、`TRUNCATE` 等写入操作。 - 对已创建的视图仅支持 `DROP` 的 DDL 操作,即 `DROP [VIEW | TABLE]`。 -## 扩展阅读 +## 另请参阅 - [创建视图](/sql-statements/sql-statement-create-view.md) - [删除视图](/sql-statements/sql-statement-drop-view.md) From 3fdab1b99a25f8014edc50e613edc7cd5309b6e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 2 Sep 2024 18:46:39 +0800 Subject: [PATCH 004/109] fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- views.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views.md b/views.md index 7ca98aaf0752..7329db7fe692 100644 --- a/views.md +++ b/views.md @@ -239,7 +239,7 @@ Query OK, 0 rows affected (0.02 sec) - TiDB 中视图为只读视图,不支持对视图进行 `UPDATE`、`INSERT`、`DELETE`、`TRUNCATE` 等写入操作。 - 对已创建的视图仅支持 `DROP` 的 DDL 操作,即 `DROP [VIEW | TABLE]`。 -## 另请参阅 +## 扩展阅读 - [创建视图](/sql-statements/sql-statement-create-view.md) - [删除视图](/sql-statements/sql-statement-drop-view.md) From 98e417ba75bc7816154dbf8c7819a672e920d2ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 3 Sep 2024 15:27:12 +0800 Subject: [PATCH 005/109] modify expression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 94 +++++++------- vector-search-functions-and-operators.md | 96 +++++++-------- vector-search-get-started-using-python.md | 97 +++++++++++---- ... => vector-search-get-started-using-sql.md | 48 +++++--- vector-search-integrate-with-django-orm.md | 116 ++++++++++++++---- vector-search-integrate-with-peewee.md | 104 +++++++++++++--- vector-search-integrate-with-sqlalchemy.md | 87 ++++++++++--- vector-search-limitations.md | 10 +- vector-search-overview.md | 26 ++-- 9 files changed, 473 insertions(+), 205 deletions(-) rename vector-search-get-started-using-sql => vector-search-get-started-using-sql.md (51%) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index f53cfbf57431..25165009e683 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -3,23 +3,23 @@ title: 向量数据类型 summary: 本文介绍 TiDB 的向量数据类型。 --- -# 向量数据类型(Vector) +# 向量数据类型 (Vector) -TiDB 提供的向量数据类型专门针对AI向量嵌入用例进行了优化。通过使用向量数据类型,可以高效地存储和查询浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`. +“向量”指的是一组浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。针对 AI 应用中大量使用到的嵌入向量 (Vector Embedding) 数据,TiDB 专门提供了向量类型用于进行高效的存储和访问。 -目前可用的向量数据类型如下: +目前有以下几种向量类型: -- `VECTOR`: 单精度浮点数序列。每一行的维度可以不同。 -- `VECTOR(D)`: 具有固定维度 `D` 的单精度浮点数序列。 +- `VECTOR`: 存储一组单精度浮点数 (Float) 向量。向量可以是任意维度。 +- `VECTOR(D)`: 存储一组单精度浮点数 (Float) 向量,向量维度固定为 `D`。 -与存储在 `JSON` 列中相比,向量数据类型具有这些优势: +相比使用 [`JSON`](/data-type-json.md) 类型,使用向量类型具有以下额外优势: -- 可指定维度。可以指定一个维度,禁止插入不同维度的向量。 -- 更优的存储格式。向量数据类型的存储效率比 `JSON` 数据类型的更高。 +- 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。 +- 存储格式更优。向量类型针对向量数据进行了特别优化,具有比 `JSON` 类型更高的空间和性能效率。 ## 语法 -向量值包含任意数量的浮点数,可以使用以下语法中的字符串来表示向量值: +可以使用以下格式的字符串来表示一个类型为向量的值: ```sql '[, , ...]' @@ -38,26 +38,26 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); INSERT INTO vector_table VALUES (2, NULL); ``` -插入语法无效的向量值将导致错误: +将不符合语法的字符串作为向量数据插入时会产生错误: ```sql [tidb]> INSERT INTO vector_table VALUES (3, '[5, ]'); ERROR 1105 (HY000): Invalid vector text: [5, ] ``` -在上例中,`embedding` 列的维度为 3,因此插入不同维度的向量会导致错误: +在下方例子中,`embedding` 向量列指定了维度为 3,因此插入不同其他维度的向量数据会引发错误: ```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-functions-and-operators.md)了解支持在向量类型上进行运算的所有函数和操作符。 -## 不同维度的向量 +## 混合存储不同维度的向量 -通过省略 `VECTOR` 类型中的维度参数,可以在同一列中存储不同维度的向量: +省略 `VECTOR` 类型中的维度参数后,就可以在同一列中存储不同维度的向量: ```sql CREATE TABLE vector_table ( @@ -69,35 +69,35 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 dimensions vector, INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK ``` -## 对比 +## 比较 -我们可以使用[比较运算符](/vector-search-functions-and-operators.md)来比较两个向量,如:`=`, `!=`, `<`, `>`, `<=`, and `>=`。有关向量数据类型的比较运算符和函数的完整列表,参阅[向量函数与操作](/vector-search-functions-and-operators.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) 进行比较,具体规则如下: -- 两个向量逐个元素进行比较,每个元素都以数值形式进行比较。 -- 第一个不匹配的元素决定哪一个向量在字典序上 _less_ 或 _greater_。 -- 如果一个向量是另一个向量的前缀,那么较短的向量为 _less_ 。 -- 长度相同、元素相同的两个向量为 _equal_ 。 -- 空向量是小于任何非空向量。 -- 两个空向量为 _equal_ 。 +- 两个向量内各个元素逐一进行数值比较。 +- 遇到第一个不一样的元素时,它们之间的数值比较结果即是两个向量之间的比较结果。 +- 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。 +- 长度相同且各个元素相同的两个向量 _相等_ 。 +- 空向量 _小于_ 任何非空向量。 +- 两个空向量 _相等_ 。 例如: - `[] < [1]` - `[1,2,3] < [1,2,3,0]` -在比较向量常量时,需要考虑执行从字符串到向量的 [显式转换](#cast),以避免基于字符串值的比较: +在进行向量比较时,可以使用 [显式转换](#类型转换-cast) 将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: ```sql --- 因为给出了字符串,所以 TiDB 会比较字符串 +-- 因为给出的实际上是字符串,因此 TiDB 会按字符串进行比较 [tidb]> SELECT '[12.0]' < '[4.0]'; +--------------------+ | '[12.0]' < '[4.0]' | @@ -106,7 +106,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, +--------------------+ 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]') | @@ -118,9 +118,9 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, ## 运算 -向量数据类型支持以元素为单位的算术运算 `+` 和 `-` 。但是,在不同维度的向量之间执行算术运算会导致错误。 +向量类型支持算术运算 `+` 和 `-`,对应的是两个向量进行以元素为单位的加法和减法。不支持对不同维度向量进行算术运算,这类运算会产生错误。 -例如: +以下是一些示例: ```sql [tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]'); @@ -143,21 +143,21 @@ mysql> SELECT VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]'); ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ``` -## 类型转换 +## 类型转换 (Cast) ### 向量与字符串之间的转换 -向量和字符串之间进行转换,可以使用以下函数: +可以使用以下函数在向量和字符串之间进行转换: - `CAST(... AS VECTOR)`: String ⇒ Vector - `CAST(... AS CHAR)`: Vector ⇒ String - `VEC_FROM_TEXT`: String ⇒ Vector - `VEC_AS_TEXT`: Vector ⇒ String -在调用接收向量数据类型的函数时,存在隐式转换: +出于易用性考虑,若函数只支持向量数据类型(如向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: ```sql --- 由于 VEC_DIMS 只接受 VECTOR 参数,因此这里有一个隐式转换: +-- VEC_DIMS 只接受向量类型,因此你可以直接传入字符串类型,TiDB 会隐式转换为向量类型: [tidb]> SELECT VEC_DIMS('[0.3, 0.5, -0.1]'); +------------------------------+ | VEC_DIMS('[0.3, 0.5, -0.1]') | @@ -166,7 +166,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +------------------------------+ 1 row in set (0.01 sec) --- 使用 VEC_FROM_TEXT 进行显式转存: +-- 也可以使用 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]')) | @@ -175,7 +175,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +---------------------------------------------+ 1 row in set (0.01 sec) --- 使用 CAST(... AS VECTOR) 进行显式转存: +-- 也可以使用 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)) | @@ -185,10 +185,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -当运算符或函数接受多种数据类型时,请使用显式转换。例如,在比较中,使用显式转换来比较向量数值而不是字符串数值: +当运算符或函数接受多种数据类型时,隐式转换不会发生,请先显式地将字符串类型转换为向量类型后,再传递给这些运算符或函数。例如,进行比较运算前,需要显式地转换字符串为向量类型,否则将会按照字符串类型进行比较,而非按照向量类型进行比较: ```sql --- 因为给出了字符串,所以 TiDB 会比较字符串: +-- 传入的类型是字符串,因此 TiDB 会按字符串进行比较: [tidb]> SELECT '[12.0]' < '[4.0]'; +--------------------+ | '[12.0]' < '[4.0]' | @@ -197,7 +197,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 +--------------------+ 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]') | @@ -207,10 +207,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -要显式地将向量转换为字符串表示,请使用 `VEC_AS_TEXT()` 函数: +向量也可以显式地转换为字符串。可使用 `VEC_AS_TEXT()` 函数: ```sql --- 规范化表示字符串: +-- 字符串首先被隐式地转换成向量,然后被显示地转为字符串,因而获得了一个规范化的格式: [tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); +--------------------------------------+ | VEC_AS_TEXT('[0.3, 0.5, -0.1]') | @@ -220,19 +220,19 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -有关其他转换函数,请参阅 [向量函数和操作](/vector-search-functions-and-operators.md)。 +若要了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 ### 向量与其他数据类型之间的转换 -目前无法直接在向量和其他数据类型(如 `JSON`)之间进行转换。您需要使用字符串作为中间类型。 +目前无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以使用字符串作为中间类型进行转换。 ## 约束 -- 支持的最大向量维数为 16383。 -- 不能在向量数据类型中存储 `NaN`、`Infinity` 或 `Infinity` 值。 -- 目前,向量数据类型不能存储双精度浮点数。未来版本将支持这一功能。 +- 向量最大支持 16383 维。 +- 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 目前向量类型只支持单精度浮点数,不支持双精度浮点数。未来版本将支持这一功能。 -有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 +有关其他限制,请参阅 [向量搜索限制](/vector-search-limitations.md)。 ## MySQL 兼容性 @@ -240,4 +240,4 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 另请参阅 -- [向量函数和操作](/tidb-cloud/vector-search-functions-and-operators.md) \ No newline at end of file +- [向量函数和操作符](/vector-search-functions-and-operators.md) \ No newline at end of file diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index a9ddf114f79a..8beee6bfde93 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -1,73 +1,73 @@ --- -title: 向量函数和操作 +title: 向量函数和操作符 summary: 本文介绍 TiDB 的向量相关函数和操作。 --- -# 向量函数和操作 +# 向量函数和操作符 ## 向量函数 -[向量数据类型](/vector-search-data-types.md)具有以下函数: +[向量数据类型](/vector-search-data-types.md)有以下几种函数: **向量距离函数:** | Function Name | Description | | --------------------------------------------------------- | ----------------------------------------------------------- | -| [VEC_L2_DISTANCE](#vec_l2_distance) | 计算两个向量之间的 L2 距离(欧氏距离) | +| [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 距离(曼哈顿距离) | +| [VEC_L1_DISTANCE](#vec_l1_distance) | 计算两个向量之间的 L1 距离 (曼哈顿距离) | **其他向量函数:** | Function Name | Description | | ------------------------------- | --------------------------------------------------- | -| [VEC_DIMS](#vec_dims) | 返回一个 vector | -| [VEC_L2_NORM](#vec_l2_norm) | 计算向量的 L2 规范(欧氏规范 | -| [VEC_FROM_TEXT](#vec_from_text) | 将字符串转换为向量 | -| [VEC_AS_TEXT](#vec_as_text) | 将向量转换为字符串 | +| [VEC_DIMS](#vec_dims) | 计算一个向量的维度 | +| [VEC_L2_NORM](#vec_l2_norm) | 计算向量的 L2 范数 (欧氏规范) | +| [VEC_FROM_TEXT](#vec_from_text) | 将字符串类型转换为向量类型 | +| [VEC_AS_TEXT](#vec_as_text) | 将向量类型转换为字符串类型 | -## 扩展内置函数和运算符 +## 扩展的内置函数和运算符 -扩展了以下内置函数和操作符,支持对[向量数据类型](/vector-search-data-types.md)进行操作。 +为了支持对 [向量数据类型](/vector-search-data-types.md) 进行操作,TiDB 扩展了以下内置函数和运算符。 **算术运算符:** | Name | Description | | :-------------------------------------------------------------------------------------- | :--------------------------------------- | -| [`+`](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) | 向量元素相减运算符 | +| [`+`](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#运算)。 +若要了解更多有关向量运算工作原理的信息,请参阅 [向量数据类型 | 运算](/vector-search-data-types.md#运算)。 -**聚合函数(GROUP BY):** +**聚合函数 (GROUP BY) :** | Name | Description | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | -| [`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) | 返回最小值 | +| [`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) | 计算最小值 | **比较函数与操作符:** | Name | Description | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -| [`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) | 返回第一个非空参数 | +| [`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) | 获得第一个非空参数 | | [`=`](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) | 安全的等于运算符 | | [`>`](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) | 返回最小参数 | +| [`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) | 检查某个值是否不在某个取值范围内 | +| [`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) | 检查数值是否不在一组数值之内 | @@ -77,21 +77,21 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 | Name | Description | | :------------------------------------------------------------------------------------------------ | :--------------------------- | -| [`CASE`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case) | Case operator | -| [`IF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if) | If/else construct | -| [`IFNULL()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | Null if/else construct | -| [`NULLIF()`](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_nullif) | Return NULL if expr1 = expr2 | +| [`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 | **转换函数:** | Name | Description | | :------------------------------------------------------------------------------------------ | :----------------------------- | -| [`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()`](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()` 的更多信息,请参阅 [向量数据类型 | 类型转换](/vector-search-data-types.md#类型转换-cast)。 -## 参考 +## 函数使用样例 ### VEC_L2_DISTANCE @@ -99,11 +99,11 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 VEC_L2_DISTANCE(vector1, vector2) ``` -使用以下公式计算两个向量之间的 L2 距离(欧氏距离): +要计算两个向量之间的 [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}}}$ -两个向量的维度必须相同。否则将返回错误信息。 +在计算的过程中,两个向量的维度必须相同。当两个向量的维度不相等时,语句将会输出错误信息。 例如: @@ -122,11 +122,11 @@ $DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ 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}}}}}}$ -两个向量的维度必须相同。否则将返回错误信息。 +在计算的过程中,两个向量的维度必须相同。当两个向量的维度不相等时,语句将会输出错误信息。 例如: @@ -145,11 +145,11 @@ $DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \ 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}}$ -两个向量的维度必须相同。否则将返回错误信息。 +在计算的过程中,两个向量的维度必须相同。当两个向量的维度不相等时,语句将会输出错误信息。 例如: @@ -168,11 +168,11 @@ $DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ VEC_L1_DISTANCE(vector1, vector2) ``` -使用以下公式计算两个向量之间的 L1 距离(曼哈顿距离): +要计算两个向量之间的 [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}|}$ -两个向量的维度必须相同。否则将返回错误信息。 +在计算的过程中,两个向量的维度必须相同。当两个向量的维度不相等时,语句将会输出错误信息。 例如: @@ -191,7 +191,7 @@ $DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ VEC_DIMS(vector) ``` -返回向量的维度。 +要计算给定向量的维度,你可以使用以下语句: 例如: @@ -217,7 +217,7 @@ VEC_DIMS(vector) VEC_L2_NORM(vector) ``` -使用以下公式计算向量的 L2 范数(欧几里得范数): +要计算给定向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0) (欧几里得范数),可以使用以下公式: $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ @@ -238,7 +238,7 @@ $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ VEC_FROM_TEXT(string) ``` -将字符串转换为向量。 +要将字符串类型转换为向量类型,可以使用以下语句: 例如: @@ -257,7 +257,7 @@ VEC_FROM_TEXT(string) VEC_AS_TEXT(vector) ``` -将向量转换为字符串 +要将向量类型转换为字符串类型,可以使用以下语句: 例如: @@ -272,7 +272,7 @@ VEC_AS_TEXT(vector) ## MySQL 兼容性 -向量函数以及内置函数和向量数据类型运算符的扩展用法是 TiDB 特有的,MySQL 不支持。 +向量数据类型只在 TiDB 中支持,MySQL 不支持。 ## 另请参阅 diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 8ccad050d001..a32f2c2851c2 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -5,22 +5,37 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 # 使用 Python 开始向量搜索 -本教程演示如何开发一个简单的人工智能应用程序,提供**语义搜索**功能。与传统的关键字搜索不同,语义搜索可以智能地理解您的查询背后的含义。例如,如果您有标题为 “狗”、“鱼 ”和 “树 ”的文档,而您搜索的是 “一种会游泳的动物”,那么应用程序会将 “鱼 ”识别为最相关的结果。 +本文展示如何开发一个简单的人工智能应用程序,并实现简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以获得与你输入的查询更加相关的结果。比如,你有标题为 “狗”、“鱼 ”和 “树 ”的文档,而你想搜索 “一种会游泳的动物”,那么语义搜索会将 “鱼 ”识别为最相关的结果。 -在本教程中,您将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和人工智能模型开发此人工智能应用程序。 +在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和人工智能模型构建人工智能应用程序。 ## 准备 +1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -在开始之前,您需要确保以下内容正确安装: + -- [Python 3.8 or higher](https://www.python.org/downloads/) -- [Git](https://git-scm.com/downloads) -- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群]([/create-tidb-cluster-serverless.md](https://dev.mysql.com/doc/refman/8.4/en/mysql.html))创建自己的 TiDB Cloud 集群。 + +
+ +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +
+ +
## 开始 -要直接运行演示,请查看 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 代码库中的示例代码。 +如果你想要查看完整的代码,可以参考 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 代码库。 ### 步骤 1. 创建一个新的 Python 项目 @@ -34,18 +49,55 @@ 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#vector-embedding)。 +- `tidb-vector`:用于与 TiDB 中的向量搜索交互的 Python 客户端。 +- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成 [向量嵌入](/vector-search-overview.md#vector-embedding)。 ### 步骤 3. 配置 TiDB 群集的连接字符串 +1. 根据不同的 TiDB 集群部署方式,配置集群的连接字符串 + + +
+ + 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**连接**。此时将显示连接对话框。 + + 3. 检查连接对话框中的配置,根据你的运行环境为其设置相应的值。 -在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + - **Endpoint Type** 设置为 `Public`. + - **Branch** 设置为 `main`. + - **Connect With** 设置为 `SQLAlchemy`. + - **Operating System** 与机器环境相匹配. + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + + 4. 单击 **PyMySQL** 标签,复制连接字符串。 + + > **Tip:** + > + > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 + + 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" + ``` + +
+ +
+ + 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - `HOST`: TiDB 集群的主机。 - `PORT`: TiDB 集群的端口。 @@ -60,11 +112,14 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" ``` +
+
+ ### 步骤 4. 初始化嵌入模型 -[嵌入模型](/vector-search-overview.md#embedding-model) 将数据转换为[向量嵌入](/vector-search-overview.md#vector-embedding)。本示例使用预训练模型 [**msmarco-MiniLM-L12-cos-v5**](https://huggingface.co/sentence-transformers/msmarco-MiniLM-L12-cos-v5) 进行文本嵌入。这个轻量级模型由 `sentence-transformers` 库提供,可将文本数据转换为 384 维向量嵌入。 +[嵌入模型](/vector-search-overview.md#embedding-model) 将数据转换为[向量嵌入](/vector-search-overview.md#vector-embedding)。本示例使用预训练模型 [**msmarco-MiniLM-L12-cos-v5**](https://huggingface.co/sentence-transformers/msmarco-MiniLM-L12-cos-v5) 将文本数据转换为向量嵌入。这个轻量级模型由 `sentence-transformers` 库提供,可将文本数据转换为 384 维向量嵌入。 -要设置模型,请将以下代码复制到 `example.py` 文件中。这段代码初始化了一个 `SentenceTransformer` 实例,并定义了一个 `text_too_embedding()` 函数供以后使用。 +将以下代码复制到 `example.py` 文件中,完成模型的设置。这段代码初始化了一个 `SentenceTransformer` 实例,并定义了一个 `text_too_embedding()` 函数用于将文本数据转换为向量数据。 ```python from sentence_transformers import SentenceTransformer @@ -81,11 +136,11 @@ def text_to_embedding(text): ### 步骤 5. 连接到 TiDB 集群 -使用 `TiDBVectorClient` 类连接到 TiDB 集群,并创建一个带有向量列的表 `embedded_documents` 作为向量存储。 +使用 `TiDBVectorClient` 类连接到 TiDB 集群,并创建一个带有向量列的表 `embedded_documents` 。 > **Note** > -> 确保向量列的维数与嵌入模型生成的向量维数一致。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度。 +> 创建的表中,向量列的维度需要与嵌入模型生成的向量维度一致。如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度, `embedded_documents` 的向量列维度也为384。 ```python import os @@ -102,14 +157,14 @@ vector_store = TiDBVectorClient( connection_string=os.environ.get('TIDB_DATABASE_URL'), # 嵌入模型生成的向量的维度。 vector_dimension=embed_model_dims, - # 如果表已经存在,则确定是否重新创建该表。 + # 如果表已经存在,则重新创建该表。 drop_existing_table=True, ) ``` -### 步骤 6. 嵌入文本数据并存储向量 +### 步骤 6. 向 **embedded_documents** 表中插入数据 -在这一步中,您将准备包含单词的示例文档,如 “狗”、“鱼 ”和 “树”。以下代码使用 `text_to_embedding()` 函数将这些文本文档转换为向量嵌入,然后将它们插入向量存储区。 +你需要准备好文本数据,比如 “狗”、“鱼 ”和 “树”。 以下代码使用 `text_to_embedding()` 函数将这些文本数据转换为向量嵌入,然后将向量嵌入插入到 `embedded_documents` 表中。 ```python documents = [ @@ -143,9 +198,9 @@ vector_store.insert( ### 步骤 7. 执行语义搜索 -在这一步中,您将搜索 “一种会游泳的动物”,它与现有文档中的任何单词都不直接匹配。 +在这一步中,假如你查询与现有文档中的任何单词都不匹配的内容,比如: “一种会游泳的动物”。 -下面的代码会再次使用 `text_to_embedding()` 函数将查询文本转换为矢量嵌入,然后使用该嵌入进行查询,找出最匹配的前三个词。 +以下的代码会再次使用 `text_to_embedding()` 函数将查询文本转换为向量嵌入,然后使用该嵌入进行查询,找出最匹配的前三个词。 ```python def print_result(query, result): @@ -170,7 +225,7 @@ Search result ("a swimming animal"): 从输出结果来看,会游泳的动物很可能是一条鱼,或者是一只有游泳天赋的狗。 -该演示展示了向量搜索如何高效地找到最相关的文档,搜索结果按向量的远近排列:距离越小,文档越相关。 +本文展示了向量搜索如何高效地找到最相关的文档,搜索结果按向量的远近排列:距离越小,文档越相关。 ## 另请参阅 diff --git a/vector-search-get-started-using-sql b/vector-search-get-started-using-sql.md similarity index 51% rename from vector-search-get-started-using-sql rename to vector-search-get-started-using-sql.md index b9df79aa5d68..5423b66cba1e 100644 --- a/vector-search-get-started-using-sql +++ b/vector-search-get-started-using-sql.md @@ -7,7 +7,7 @@ summary: 了解如何使用 SQL 语句快速开始使用 TiDB Cloud 中的向量 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): +本文档展示如何使用 SQL 语句开始 TiDB 向量搜索。你将了解如何使用 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html): - 连接到 TiDB 集群。 - 创建向量表 @@ -15,17 +15,31 @@ TiDB 扩展了 MySQL 语法以支持 [向量搜索](/vector-search-overview.md) - 执行向量搜索查询 ## 准备 +1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -在使用向量搜索之前,您需要确认: + -- 安装了 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 -- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +
+ + - 安装了[MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 + - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 + +
+ +
+ + - 安装了 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 + - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +
+ +
## 开始 ### 步骤 1. 连接到 TiDB 集群 -复制连接命令并将其粘贴到终端。以下是 macOS 的示例: +将连接命令输入至终端。以下是 macOS 的示例: ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' @@ -33,9 +47,9 @@ TiDB 扩展了 MySQL 语法以支持 [向量搜索](/vector-search-overview.md) ### 步骤 2. 创建向量表 -有了向量搜索支持,您就可以使用 `VECTOR` 类型列在 TiDB 中存储 [向量嵌入](/vector-search-overview.md#vector-embedding)。 +TiDB 支持了向量搜索,允许用户在创建表时使用 `VECTOR` 声明 [向量](/vector-search-overview.md#vector-embedding) 列。 -要创建带有三维 `VECTOR` 列的表,请使用 MySQL CLI 执行以下 SQL 语句: +要创建带有三维 `VECTOR` 列的表,你可以使用 MySQL CLI 执行以下 SQL 语句: ```sql USE test; @@ -43,7 +57,7 @@ CREATE TABLE embedded_documents ( id INT PRIMARY KEY, -- 存储文档的原始内容。 document TEXT, - -- 存储文件的向量表示。 + -- 存储文档的向量表示。 embedding VECTOR(3) ); ``` @@ -54,9 +68,9 @@ CREATE TABLE embedded_documents ( Query OK, 0 rows affected (0.27 sec) ``` -### 步骤 3. 存储向量嵌入 +### 步骤 3. 向表中插入向量 -将三行数据及其 [向量嵌入](/vector-search-overview.md#vector-embedding) 插入 `embedded_documents` 表: +将三行附带 [向量](/vector-search-overview.md#vector-embedding) 的数据及其 插入 `embedded_documents` 表: ```sql INSERT INTO embedded_documents @@ -75,13 +89,13 @@ Records: 3 Duplicates: 0 Warnings: 0 > **Note** > -> 本示例简化了向量嵌入的维数,仅使用三维向量进行演示。 +> 为了方便展示,本示例简化了向量的维数,仅使用三维向量。 > -> 在实际应用中,[嵌入模型](/vector-search-overview.md#embedding-model) 通常会产生数百或数千维的向量嵌入。 +> 在实际应用中,[嵌入模型](/vector-search-overview.md#embedding-model) 通常会产生数百或数千维的向量。 ### 步骤 4. 查询向量表 -要验证文件是否已正确插入,请查询 `embedded_documents` 表: +要验证文件是否已正确插入,你可以查询 `embedded_documents` 表: ```sql SELECT * FROM embedded_documents; @@ -102,11 +116,11 @@ SELECT * FROM embedded_documents; ### 步骤 5. 执行向量搜索查询 -与全文搜索类似,在使用向量搜索时,用户向应用程序提供搜索词。 +与全文搜索类似,在使用向量搜索时,你需要指定搜索词。 -在本例中,搜索词是 “一种会游泳的动物”,其对应的向量嵌入是 `[1,2,3]`。在实际应用中,需要使用嵌入模型将用户的搜索词转换为向量嵌入。 +在本例中,搜索词是 “一种会游泳的动物”,其对应的向量是 `[1,2,3]`。在实际应用中,需要使用嵌入模型将用户的搜索词转换为向量。 -执行以下 SQL 语句后,TiDB 将通过计算和排序向量嵌入之间的余弦距离(`vec_cosine_distance`),找出最接近搜索词的前三个数据。 +在以下执行的 SQL 语句中,TiDB 会计算 `[1,2,3]` 与表中向量的余弦距离 (`vec_cosine_distance`),然后进行排序输出表中最接近搜索向量 (余弦距离最小) 的前三个向量。 ```sql SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance @@ -128,7 +142,7 @@ LIMIT 3; 3 rows in set (0.15 sec) ``` -从输出结果来看,会游泳的动物很可能是一条鱼,或者是一只有游泳天赋的狗。 +从输出结果来看,会游泳的动物很可能是 “一条鱼” ,或者是一只 “有游泳天赋的狗”。 ## 另请参阅 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 43e275896688..600638888dda 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -1,23 +1,39 @@ --- -title: TiDB 向量搜索与 Django ORM 结合 -summary: 了解如何将 TiDB 向量搜索与 Django ORM 结合,以存储嵌入并执行语义搜索。 +title: TiDB 向量搜索在 Django ORM 中的使用 +summary: 了解如何在 Django ORM 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 --- -# TiDB 向量搜索与 Django ORM 结合 +# TiDB 向量搜索在 Django ORM 中的使用 -本教程将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储嵌入和执行向量搜索查询。 +本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 ## 准备 +1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -要实现本部分的内容,需要确保安装以下内容: + + +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 + +
+ +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +
+ +
-- [Python 3.8 or higher](https://www.python.org/downloads/) -- [Git](https://git-scm.com/downloads) -- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 -您可以通过以下步骤快速了解如何将 TiDB 向量搜索与 Django ORM 集成。 +你可以通过以下步骤快速了解如何在 Django ORM 中使用 TiDB 向量搜索。 ### 步骤 1. 克隆仓库 @@ -45,7 +61,7 @@ source .venv/bin/activate pip install -r requirements.txt ``` -您可以为现有项目安装以下软件包: +你也可以直接为项目安装以下依赖项: ```bash pip install Django django-tidb mysqlclient numpy python-dotenv @@ -55,18 +71,68 @@ pip install Django django-tidb mysqlclient numpy python-dotenv #### 什么是 `django-tidb`? -`django-tidb`使用django框架提供了与tidb交互的示例,它实现了 Django ORM 以支持 TiDB 的向量搜索,并解决了 TiDB 和 Django 之间的兼容性问题。 +`django-tidb`使用 django 框架提供了与 tidb 交互的示例,它实现了 Django ORM 以支持 TiDB 的向量搜索,并解决了 TiDB 和 Django 之间的兼容性问题。 要安装 `django-tidb`,请选择与 Django 版本相匹配的版本。例如,如果使用的是 `django==4.2.*`, 则安装 `django-tidb===4.2.*`。次版本号不必相同,但建议使用最新的次版本。 更多信息,请参阅 [django-tidb repository](https://github.com/pingcap/django-tidb)。 ### 步骤 4. 配置环境变量 +1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ + 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**连接**。此时将显示连接对话框。 + + 3. 确保连接对话框中的配置符合你的运行环境。 + + - **Endpoint Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与你的机器环境相匹配 + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + + 4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 + + 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 + ``` -在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 +
- - `TIDB_HOST`: TiDB 集群的主机。 - - `TIDB_PORT`: TiDB 集群的端口。 +
+ + 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + + - `TIDB_HOST`: TiDB 集群的主机号。 + - `TIDB_PORT`: TiDB 集群的端口号。 - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - `TIDB_DATABASE`: 要连接的数据库名称。 @@ -83,6 +149,10 @@ pip install Django django-tidb mysqlclient numpy python-dotenv TIDB_CA_PATH=/etc/ssl/cert.pem ``` +
+ +
+ ### Step 5. 运行 demo 迁移数据库模式: @@ -97,17 +167,17 @@ python manage.py migrate python manage.py runserver ``` -打开浏览器,访问 `http://127.0.0.1:8000` 尝试演示应用程序。以下是可用的 API 路径: +打开浏览器,访问 `http://127.0.0.1:8000` 查看程序的可视化界面。以下是可用的 API 路径: | API Path | Description | | --------------------------------------- | ---------------------------------------- | -| `POST: /insert_documents` | Insert documents with embeddings. | -| `GET: /get_nearest_neighbors_documents` | Get the 3-nearest neighbor documents. | -| `GET: /get_documents_within_distance` | Get documents within a certain distance. | +| `POST: /insert_documents` | 插入含有向量的文件。 | +| `GET: /get_nearest_neighbors_documents` | 获取距离最近的3个文件。 | +| `GET: /get_documents_within_distance` | 获取处于给定距离内的所有文件。 | ## 示例代码片段 -您可以参考以下示例代码片段来完成自己的应用程序开发。 +你可以参考以下示例代码片段来完成自己的程序开发。 ### 连接到 TiDB 集群 @@ -145,9 +215,9 @@ if TIDB_CA_PATH: #### 定义向量列 -`tidb-django` 提供了一个 `VectorField` 来在表中存储向量嵌入。 +`tidb-django` 提供了一个 `VectorField` ,可以在表中用来表示和存储向量类型。 -创建一个表格,其中有一列名为 `embedding` ,用于存储三维向量。 +创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 ```python class Document(models.Model): @@ -172,7 +242,7 @@ TiDB 向量支持以下距离函数: - `CosineDistance` - `NegativeInnerProduct` -根据余弦距离函数,搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 ```python results = Document.objects.annotate( @@ -182,7 +252,7 @@ results = Document.objects.annotate( ### 搜索一定距离内的向量 -搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python results = Document.objects.annotate( diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 5764ffc49d8d..76fc59907d8e 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -1,23 +1,38 @@ --- -title: TiDB 向量搜索与 peewee 相结合 -summary: 了解如何将 TiDB 向量搜索与 peewee 集成,以存储嵌入信息并执行语义搜索。 +title: TiDB 向量搜索在 peewee 中的使用 +summary: 了解如何在 peewee 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 --- -# TiDB 向量搜索与 peewee 结合 +# TiDB 向量搜索在 peewee 中的使用 -本教程将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 TiDB 向量搜索交互、存储嵌入和执行向量搜索查询。 +本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 ## 准备 +1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -要实现本部分的内容,需要确保安装以下内容: + -- [Python 3.8 or higher](https://www.python.org/downloads/) installed. -- [Git](https://git-scm.com/downloads) installed. -- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 + +
+ +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +
+ +
## 运行示例应用程序 -通过以下步骤,您可以快速了解如何将 TiDB 向量搜索与 peewee 结合。 +你可以通过以下步骤快速了解如何在 peewee 中使用 TiDB 向量搜索。 ### Step 1. 克隆仓库 @@ -45,7 +60,7 @@ source .venv/bin/activate pip install -r requirements.txt ``` -您可以为现有项目安装以下软件包: +你也可以直接为项目安装以下依赖项: ```bash pip install peewee pymysql python-dotenv tidb-vector @@ -53,10 +68,61 @@ pip install peewee pymysql python-dotenv tidb-vector ### 步骤 4. 配置环境变量 -在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 +1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ + 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**连接**。此时将显示连接对话框。 + + 3. 确保连接对话框中的配置符合你的运行环境。 + + - **Endpoint Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与你的机器环境相匹配 + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + + 4. 从连接对话框中复制连接参数。 + + > **Tip:** + > + > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 + + 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 + ``` + +
- - `TIDB_HOST`: TiDB 集群的主机。 - - `TIDB_PORT`: TiDB 集群的端口。 +
+ + 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + + - `TIDB_HOST`: TiDB 集群的主机号。 + - `TIDB_PORT`: TiDB 集群的端口号。 - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - `TIDB_DATABASE`: 要连接的数据库名称。 @@ -73,6 +139,10 @@ pip install peewee pymysql python-dotenv tidb-vector TIDB_CA_PATH=/etc/ssl/cert.pem ``` +
+ +
+ ### 步骤 5. 运行 demo ```bash @@ -98,7 +168,7 @@ Get documents within a certain distance: ## 示例代码片段 -您可以参考以下示例代码片段来开发您的应用程序。 +你可以参考以下示例代码片段来完成自己的程序开发。 ### 创建向量表 @@ -141,7 +211,7 @@ db = MySQLDatabase( #### 定义向量列 -创建一个表格,其中有一列名为 `peewee_demo_documents`,用于存储一个三维向量。 +创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 ```python class Document(Model): @@ -163,7 +233,7 @@ Document.create(content='tree', embedding=[1, 0, 0]) ### 搜索近邻向量 -根据余弦距离函数,搜索与查询向量 `[1, 2, 3]` 语义最接近的前 3 个向量。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 ```python distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') @@ -172,7 +242,7 @@ results = Document.select(Document, distance).order_by(distance).limit(3) ### 搜索一定距离内的向量 -搜索与查询向量 `[1, 2, 3]` 的余弦距离小于 0.2 的文档。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python distance_expression = Document.embedding.cosine_distance([1, 2, 3]) diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index a044e6696202..bb6d1fa1a10c 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -1,24 +1,39 @@ --- -title: TiDB 向量搜索与 SQLAlchemy 结合 -summary: 了解如何将 TiDB 向量搜索与 SQLAlchemy 结合,以存储embedding并执行语义搜索。 +title: TiDB 向量搜索在 SQLAlchemy 中的使用 +summary: 了解如何在 SQLAlchemy 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 --- -# TiDB 向量搜索与 SQLAlchemy 结合 +# TiDB 向量搜索在 SQLAlchemy 中的使用 -本教程将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md) 交互、存储嵌入和执行向量搜索查询。 +本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md)进行交互、存储向量和执行向量搜索查询。 ## 准备 -要实现本部分的内容,需要确保安装以下内容: +1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, + -- [Python 3.8 or higher](https://www.python.org/downloads/) -- [Git](https://git-scm.com/downloads) -- TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 + +
+ +
+ + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 + +
+ +
## 运行示例应用程序 -您可以通过以下步骤快速了解如何将 TiDB 向量搜索与 SQLAlchemy 结合。 +你可以通过以下步骤快速了解如何在 SQLAlchemy 中使用 TiDB 向量搜索。 ### 步骤 1. 克隆仓库 @@ -46,15 +61,53 @@ source .venv/bin/activate pip install -r requirements.txt ``` -您可以为现有项目安装以下软件包: +你也可以直接为项目安装以下依赖项: ```bash pip install pymysql python-dotenv sqlalchemy tidb-vector ``` ### 步骤 4. 配置环境变量 +1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
+ + 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**连接**。此时将显示连接对话框。 + + 3. 确保连接对话框中的配置符合你的运行环境。 + + - **Endpoint Type** 设置为 `Public` + - **Branch** 设置为 `main` + - **Connect With** 设置为 `General` + - **Operating System** 与你的机器环境相匹配 + + > **Tip:** + > + > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + 4. 单击 **PyMySQL** 标签,复制连接字符串。 + + > **Tip:** + > + > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 + + 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" + ``` + +
+ +
+ + 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - `HOST`: TiDB 集群的主机。 - `PORT`: TiDB 集群的端口。 @@ -69,6 +122,10 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector TIDB_DATABASE_URL="mysql+pymysql://.root:@127.0.0.1:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" ``` +
+ +
+ ### 步骤 5. 运行demo ```bash @@ -94,7 +151,7 @@ Get documents within a certain distance: ## 示例代码片段 -您可以参考以下示例代码片段来开发您的应用程序。 +你可以参考以下示例代码片段来完成自己的程序开发。 ### 创建向量表 @@ -116,7 +173,7 @@ engine = create_engine(tidb_connection_string) #### 定义向量列 -创建一个表格,其中有一列名为 `embedding`,用于存储三维向量。 +创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 ```python Base = declarative_base() @@ -140,7 +197,7 @@ with Session(engine) as session: ### 搜索近邻向量 -根据余弦距离函数,搜索与查询向量`[1, 2, 3]`”`语义最接近的前 3 篇向量。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 ```python with Session(engine) as session: @@ -152,7 +209,7 @@ with Session(engine) as session: ### 搜索一定距离内的向量 -搜索与查询向量`[1, 2, 3]`的余弦距离小于 0.2 的文档。 +我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python with Session(engine) as session: diff --git a/vector-search-limitations.md b/vector-search-limitations.md index a01b6811b3e3..84fec504da03 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -5,16 +5,16 @@ summary: 本文介绍 TiDB 的向量搜索限制。 # 向量搜索限制 -本文档描述了 TiDB 向量搜索的已知限制。我们将继续努力,通过添加更多功能来提升您的使用体验。 +本文档介绍 TiDB 向量搜索的已知限制。我们将继续努力,通过添加更多功能来提升您的使用体验。 -- 最大支持16383维[向量](/vector-search-data-types.md)。 - -- 向量数据仅支持单精度浮点数 (Float32)。 +- 向量最大支持 16383 维。 +- 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 目前向量类型只支持单精度浮点数,不支持双精度浮点数。未来版本将支持这一功能。 ## 反馈 -我们非常重视您的反馈意见,并随时准备提供帮助: +我们非常重视您的反馈意见,并随时准备为您提供帮助: - [Join our Discord](https://discord.gg/zcqexutz2R) - [Visit our Support Portal](https://tidb.support.pingcap.com/) \ No newline at end of file diff --git a/vector-search-overview.md b/vector-search-overview.md index d8800a6d3103..27d6b5e65f92 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -1,50 +1,52 @@ --- title: 向量搜索概述 -summary: 了解 TiDB 中的向量搜索。该功能提供了一种高效的搜索解决方案,可跨文档、图像、音频和视频等各种数据类型执行语义相似性搜索。 +summary: 介绍 TiDB 中的向量搜索。该功能提供了一种高效的搜索解决方案,可跨文档、图像、音频和视频等各种数据类型执行语义相似性搜索。 --- # 向量搜索概述 -TiDB 向量搜索提供了一种高效的搜索解决方案,可在各种数据类型(包括文档、图像、音频和视频)中执行语义相似性搜索。该功能使开发人员能够使用熟悉的 MySQL 技能,轻松构建具有生成人工智能(AI)功能的可扩展应用程序。 +TiDB 向量搜索提供了一种高效的搜索解决方案,它可以在各种数据类型 (文档、图像、音频、视频) 中进行语义搜索。 熟悉 MySQL 的开发人员可以方便、轻松的使用 TiDB 向量搜索构建自己的 AI 程序。 ## 概念 -向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。这不同于传统的全文搜索,后者主要依赖于精确的关键词匹配和词频。 +向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。相比于传统的全文搜索主要依赖于精确的关键词匹配和词频,向量搜索通过将数据(如文本、图像或音频)转换为高维向量,并利用这些向量的相似度进行查询。这种方法能够捕捉数据的语义特征和上下文信息,从而更准确地理解用户意图,即使搜索词语并不完全匹配数据库中的内容。 例如,全文搜索 “一种会游泳的动物” 只会返回包含这些精确关键词的结果。相比之下,向量搜索可以返回其他游泳动物的结果,如鱼或鸭子,即使没有准确的关键字。 ### 向量嵌入 -向量嵌入(vector embedding)又称嵌入(embedding),是在高维空间中表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的含义和上下文。 +向量嵌入 (vector embedding) 又称嵌入 (embedding) ,是在高维空间中表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的语义特征和上下文。 向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 -TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化向量嵌入的存储和检索,增强其在人工智能领域的应用。您可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询以查找最相关的数据。 +TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化向量嵌入的存储和检索,增强其在人工智能领域的应用。 你可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询以查找最相关的数据。 ### 嵌入模型 嵌入模型是将数据转换为[向量嵌入](#vector-embedding)的算法。 -选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,您可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 +选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 -要了解如何为特定数据类型生成向量嵌入,请参阅嵌入提供程序集成教程或示例。 +如果你想要了解如何为特定数据类型生成向量嵌入,请参阅嵌入模型的教程或示例。 ## 向量搜索如何工作 -将原始数据转换为向量嵌入并存储在 TiDB 中后,您的应用程序就可以执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 +在将原始数据转换为向量并存储在 TiDB 中后,你的应用程序就可以开始执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 -TiDB Cloud 中的向量搜索(Vector Search)通过使用[距离函数](/vector-search-functions-and-operators.md)来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。最接近查询的向量代表意义最相似的数据。 +TiDB 中的向量搜索 (Vector Search) 通过使用 [距离函数](/vector-search-functions-and-operators.md) 来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。与给定向量的距离最小的向量代表最相似的数据。 ![The Schematic TiDB Vector Search](/media/vector-search/embedding-search.png) -作为一个具有向量搜索功能的关系数据库,TiDB 使您能够在一个数据库中存储数据及其相应的向量嵌入。您可以使用不同的列将它们存储在同一个表中,也可以将它们分离到不同的表中,并在检索时使用 `JOIN` 查询将它们组合在一起。 +TiDB 是一个支持向量搜索的关系数据库,这意味着你可以在同一个数据库里存储数据和它们的向量表示 (向量嵌入) 。你可以选择把数据和它们的向量放在同一个表里的不同列中,也可以把它们放在不同的表里。在需要搜索的时候,再用 JOIN 查询把这些表的数据组合起来使用。 + + ## 使用案例 -### 检索增强生成(Retrieval-Augmented Generation, RAG) +### 检索增强生成 (Retrieval-Augmented Generation, RAG) -检索增强生成(RAG)是一种旨在优化大型语言模型(LLM)输出的架构。通过使用向量搜索,RAG 应用程序可以在数据库中存储向量嵌入,并在 LLM 生成回复时检索相关文档作为附加上下文,从而提高回复的质量和相关性。 +检索增强生成(RAG)是一种优化大型语言模型(LLM)输出的架构。通过使用向量搜索,RAG 应用程序可以在数据库中存储向量嵌入,并在 LLM 生成回复时检索相关文档作为附加上下文,从而提高回复的质量和相关性。 ### 语义搜索 From 9bd83d6f9b6c53770cfb877a1f3011ba52cdfcaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 3 Sep 2024 15:31:43 +0800 Subject: [PATCH 006/109] fix ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index a32f2c2851c2..488dbc934dd6 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -19,7 +19,7 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 - [Python 3.8 or higher](https://www.python.org/downloads/) - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群]([/create-tidb-cluster-serverless.md](https://dev.mysql.com/doc/refman/8.4/en/mysql.html))创建自己的 TiDB Cloud 集群。 + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 @@ -99,7 +99,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - - `HOST`: TiDB 集群的主机。 + - `HOST`: TiDB 集群的主机号。 - `PORT`: TiDB 集群的端口。 - `USERNAME`: 连接 TiDB 集群的用户名。 - `PASSWORD`: 连接 TiDB 集群的密码。 From 52934cbfd0c51b17014c19e1bec9ee395c15a2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 3 Sep 2024 16:37:45 +0800 Subject: [PATCH 007/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-functions-and-operators.md | 26 +++++++------- vector-search-get-started-using-python.md | 42 +++++++++-------------- vector-search-limitations.md | 2 +- vector-search-overview.md | 6 ++-- 4 files changed, 33 insertions(+), 43 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 8beee6bfde93..4d0009e19632 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -8,36 +8,36 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 ## 向量函数 -[向量数据类型](/vector-search-data-types.md)有以下几种函数: +TiDB 为 [向量数据类型](/vector-search-data-types.md) 设计了以下函数: **向量距离函数:** | Function Name | Description | | --------------------------------------------------------- | ----------------------------------------------------------- | -| [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 距离 (曼哈顿距离) | +| [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 距离 (曼哈顿距离) | **其他向量函数:** | Function Name | Description | | ------------------------------- | --------------------------------------------------- | -| [VEC_DIMS](#vec_dims) | 计算一个向量的维度 | -| [VEC_L2_NORM](#vec_l2_norm) | 计算向量的 L2 范数 (欧氏规范) | +| [VEC_DIMS](#vec_dims) | 返回向量的维度 | +| [VEC_L2_NORM](#vec_l2_norm) | 返回向量的 L2 范数 (欧氏规范) | | [VEC_FROM_TEXT](#vec_from_text) | 将字符串类型转换为向量类型 | | [VEC_AS_TEXT](#vec_as_text) | 将向量类型转换为字符串类型 | ## 扩展的内置函数和运算符 -为了支持对 [向量数据类型](/vector-search-data-types.md) 进行操作,TiDB 扩展了以下内置函数和运算符。 +TiDB 扩展了以下内置函数和运算符,它们额外也支持[向量数据类型](/vector-search-data-types.md)。 **算术运算符:** | Name | Description | | :-------------------------------------------------------------------------------------- | :--------------------------------------- | | [`+`](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) | 向量类型的相减运算符 | +| [`-`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html#operator_minus) | 向量类型的减法运算符 | 若要了解更多有关向量运算工作原理的信息,请参阅 [向量数据类型 | 运算](/vector-search-data-types.md#运算)。 @@ -45,10 +45,10 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 | Name | Description | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | -| [`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) | 计算最小值 | +| [`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) | 返回最小值 | **比较函数与操作符:** diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 488dbc934dd6..ce61636f4f33 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -5,37 +5,27 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 # 使用 Python 开始向量搜索 -本文展示如何开发一个简单的人工智能应用程序,并实现简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以获得与你输入的查询更加相关的结果。比如,你有标题为 “狗”、“鱼 ”和 “树 ”的文档,而你想搜索 “一种会游泳的动物”,那么语义搜索会将 “鱼 ”识别为最相关的结果。 +本文展示如何开发一个简单的 AI 应用,这个 AI 应用实现了简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以智能地“理解”你的输入,返回更相关的结果。例如,在“狗”、“鱼”和“树”这三个内容中搜索“一种会游泳的动物”时,语义搜索会将“鱼”作为最相关的结果。 -在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和人工智能模型构建人工智能应用程序。 +在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型构建 AI 应用。 ## 准备 -1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +- TiDB Serverless 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 - - -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 - -
+- 本地部署的 TiDB 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 - -
- -
## 开始 -如果你想要查看完整的代码,可以参考 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 代码库。 +以下是从零构建这个应用的详细步骤,你也可以从 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 开源代码库获取到完整代码,直接运行示例。 ### 步骤 1. 创建一个新的 Python 项目 @@ -55,18 +45,18 @@ touch example.py pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv ``` -- `tidb-vector`:用于与 TiDB 中的向量搜索交互的 Python 客户端。 +- `tidb-vector`:用于与 TiDB 向量搜索交互的 Python 客户端。 - [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成 [向量嵌入](/vector-search-overview.md#vector-embedding)。 -### 步骤 3. 配置 TiDB 群集的连接字符串 +### 步骤 3. 配置 TiDB 集群的连接字符串 1. 根据不同的 TiDB 集群部署方式,配置集群的连接字符串
- 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + 1. 在 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 - 2. 单击右上角的**连接**。此时将显示连接对话框。 + 2. 单击右上角的**Connect**。此时将显示连接对话框。 3. 检查连接对话框中的配置,根据你的运行环境为其设置相应的值。 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 84fec504da03..549cbcc1d29e 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -5,7 +5,7 @@ summary: 本文介绍 TiDB 的向量搜索限制。 # 向量搜索限制 -本文档介绍 TiDB 向量搜索的已知限制。我们将继续努力,通过添加更多功能来提升您的使用体验。 +本文档介绍 TiDB 向量搜索的已知限制。我们会持续新增更多功能来提升使用体验。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 diff --git a/vector-search-overview.md b/vector-search-overview.md index 27d6b5e65f92..ce053db1e30f 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -1,11 +1,11 @@ --- title: 向量搜索概述 -summary: 介绍 TiDB 中的向量搜索。该功能提供了一种高效的搜索解决方案,可跨文档、图像、音频和视频等各种数据类型执行语义相似性搜索。 +summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图像、音频和视频等各种数据类型进行语义搜索。 --- # 向量搜索概述 -TiDB 向量搜索提供了一种高效的搜索解决方案,它可以在各种数据类型 (文档、图像、音频、视频) 中进行语义搜索。 熟悉 MySQL 的开发人员可以方便、轻松的使用 TiDB 向量搜索构建自己的 AI 程序。 +TiDB 向量搜索 (beta) 提供了在多种数据类型之间进行语义搜索的高级搜索方案,可以对文档、图像、音频、视频等不同数据类型进行语义上的相似度搜索。TiDB 向量搜索以 MySQL 兼容的 SQL 语法提供,熟悉 MySQL 的开发人员可轻松地基于此构建例如生成式人工智能 (GAI) 应用。 ## 概念 @@ -34,7 +34,7 @@ TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化 在将原始数据转换为向量并存储在 TiDB 中后,你的应用程序就可以开始执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 -TiDB 中的向量搜索 (Vector Search) 通过使用 [距离函数](/vector-search-functions-and-operators.md) 来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。与给定向量的距离最小的向量代表最相似的数据。 +TiDB 向量搜索 (Vector Search) 通过使用 [距离函数](/vector-search-functions-and-operators.md) 来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。与给定向量的距离最小的向量代表最相似的数据。 ![The Schematic TiDB Vector Search](/media/vector-search/embedding-search.png) From 26027f95e77584bf5e15e290be5a77387f9b41e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 3 Sep 2024 16:50:22 +0800 Subject: [PATCH 008/109] fix ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 2 +- vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index ce61636f4f33..27133d2f08ef 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -219,4 +219,4 @@ Search result ("a swimming animal"): ## 另请参阅 -- [Vector Data Types](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file +- [Vector Data Types](/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 index 600638888dda..8513137a354a 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -262,4 +262,4 @@ results = Document.objects.annotate( ## 另请参阅 -- [向量数据类型](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index bb6d1fa1a10c..9b5766671189 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -5,7 +5,7 @@ summary: 了解如何在 SQLAlchemy 中 TiDB 使用向量搜索,,以存储 # TiDB 向量搜索在 SQLAlchemy 中的使用 -本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/tidb-cloud/vector-search-overview.md)进行交互、存储向量和执行向量搜索查询。 +本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互、存储向量和执行向量搜索查询。 ## 准备 From df68638686c2cb1396d83df2ef5ed2fea7b5a3cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 3 Sep 2024 17:08:19 +0800 Subject: [PATCH 009/109] fix ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-functions-and-operators.md | 2 +- vector-search-get-started-using-python.md | 4 ++-- vector-search-get-started-using-sql.md | 6 +++--- vector-search-overview.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 4d0009e19632..518fd182f51b 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -71,7 +71,7 @@ TiDB 扩展了以下内置函数和运算符,它们额外也支持[向量数 | [`!=`, `<>`](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#comparison)。 +有关如何比较向量的更多信息,请参阅 [向量数据类型 | 比较](/vector-search-data-types.md#比较)。 **控制流函数:** diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 27133d2f08ef..c1c22c50abf4 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -46,7 +46,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv ``` - `tidb-vector`:用于与 TiDB 向量搜索交互的 Python 客户端。 -- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成 [向量嵌入](/vector-search-overview.md#vector-embedding)。 +- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成 [向量嵌入](/vector-search-overview.md#向量嵌入)。 ### 步骤 3. 配置 TiDB 集群的连接字符串 1. 根据不同的 TiDB 集群部署方式,配置集群的连接字符串 @@ -107,7 +107,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv ### 步骤 4. 初始化嵌入模型 -[嵌入模型](/vector-search-overview.md#embedding-model) 将数据转换为[向量嵌入](/vector-search-overview.md#vector-embedding)。本示例使用预训练模型 [**msmarco-MiniLM-L12-cos-v5**](https://huggingface.co/sentence-transformers/msmarco-MiniLM-L12-cos-v5) 将文本数据转换为向量嵌入。这个轻量级模型由 `sentence-transformers` 库提供,可将文本数据转换为 384 维向量嵌入。 +[嵌入模型](/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()` 函数用于将文本数据转换为向量数据。 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index 5423b66cba1e..ac9f1103a7f3 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -47,7 +47,7 @@ TiDB 扩展了 MySQL 语法以支持 [向量搜索](/vector-search-overview.md) ### 步骤 2. 创建向量表 -TiDB 支持了向量搜索,允许用户在创建表时使用 `VECTOR` 声明 [向量](/vector-search-overview.md#vector-embedding) 列。 +TiDB 支持了向量搜索,允许用户在创建表时使用 `VECTOR` 声明 [向量](/vector-search-overview.md#向量嵌入) 列。 要创建带有三维 `VECTOR` 列的表,你可以使用 MySQL CLI 执行以下 SQL 语句: @@ -70,7 +70,7 @@ Query OK, 0 rows affected (0.27 sec) ### 步骤 3. 向表中插入向量 -将三行附带 [向量](/vector-search-overview.md#vector-embedding) 的数据及其 插入 `embedded_documents` 表: +将三行附带 [向量](/vector-search-overview.md#向量嵌入) 的数据及其 插入 `embedded_documents` 表: ```sql INSERT INTO embedded_documents @@ -91,7 +91,7 @@ Records: 3 Duplicates: 0 Warnings: 0 > > 为了方便展示,本示例简化了向量的维数,仅使用三维向量。 > -> 在实际应用中,[嵌入模型](/vector-search-overview.md#embedding-model) 通常会产生数百或数千维的向量。 +> 在实际应用中,[嵌入模型](/vector-search-overview.md#嵌入模型) 通常会产生数百或数千维的向量。 ### 步骤 4. 查询向量表 diff --git a/vector-search-overview.md b/vector-search-overview.md index ce053db1e30f..00d39d7fd045 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -24,7 +24,7 @@ TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化 ### 嵌入模型 -嵌入模型是将数据转换为[向量嵌入](#vector-embedding)的算法。 +嵌入模型是将数据转换为[向量嵌入](#向量嵌入)的算法。 选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 From febd53465d6f4d9a41684290724457a4bb826e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 4 Sep 2024 10:33:43 +0800 Subject: [PATCH 010/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-sql.md | 36 ++++++++++------------ vector-search-integrate-with-django-orm.md | 33 +++++++------------- vector-search-integrate-with-peewee.md | 33 +++++++------------- vector-search-integrate-with-sqlalchemy.md | 33 +++++++------------- 4 files changed, 49 insertions(+), 86 deletions(-) diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index ac9f1103a7f3..b1f0e0700b68 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -15,36 +15,32 @@ TiDB 扩展了 MySQL 语法以支持 [向量搜索](/vector-search-overview.md) - 执行向量搜索查询 ## 准备 -1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +- TiDB Serverless 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 - - -
- - - 安装了[MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 - - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 - -
- -
- - - 安装了 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI)。 - - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 - -
- -
+- 本地部署的 TiDB 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 开始 ### 步骤 1. 连接到 TiDB 集群 将连接命令输入至终端。以下是 macOS 的示例: - - ```bash +- TiDB Serverless 集群 + ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' ``` +- 本地部署的 TiDB 集群 + ```bash + mysql --comments --host 127.0.0.1 --port 4000 -u root + ``` + ### 步骤 2. 创建向量表 TiDB 支持了向量搜索,允许用户在创建表时使用 `VECTOR` 声明 [向量](/vector-search-overview.md#向量嵌入) 列。 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 8513137a354a..ec19dce63443 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -8,27 +8,16 @@ summary: 了解如何在 Django ORM 中 TiDB 使用向量搜索,,以存储 本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 ## 准备 -1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +- TiDB Serverless 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 - - -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 - -
- -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 - -
- -
+- 本地部署的 TiDB 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 @@ -84,9 +73,9 @@ pip install Django django-tidb mysqlclient numpy python-dotenv
- 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 - 2. 单击右上角的**连接**。此时将显示连接对话框。 + 2. 单击右上角的**Connect**。此时将显示连接对话框。 3. 确保连接对话框中的配置符合你的运行环境。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 76fc59907d8e..f63dbfc75eaa 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -8,27 +8,16 @@ summary: 了解如何在 peewee 中 TiDB 使用向量搜索,,以存储向量 本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 ## 准备 -1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +- TiDB Serverless 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 - - -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 - -
- -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 - -
- -
+- 本地部署的 TiDB 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 @@ -74,9 +63,9 @@ pip install peewee pymysql python-dotenv tidb-vector
- 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 - 2. 单击右上角的**连接**。此时将显示连接对话框。 + 2. 单击右上角的**Connect**。此时将显示连接对话框。 3. 确保连接对话框中的配置符合你的运行环境。 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 9b5766671189..1a25d3a2d7df 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -9,27 +9,16 @@ summary: 了解如何在 SQLAlchemy 中 TiDB 使用向量搜索,,以存储 ## 准备 +在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, +- TiDB Serverless 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 -1. 在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, - - -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serveless 群集。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://docs.pingcap.com/tidbcloud/create-tidb-cluster-serverless)创建自己的 TiDB Cloud 集群。 - -
- -
- - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 - -
- -
+- 本地部署的 TiDB 集群 + - [Python 3.8 or higher](https://www.python.org/downloads/) + - [Git](https://git-scm.com/downloads) + - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 ## 运行示例应用程序 @@ -74,9 +63,9 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector
- 1. 在 [**群集**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 + 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 - 2. 单击右上角的**连接**。此时将显示连接对话框。 + 2. 单击右上角的**Connect**。此时将显示连接对话框。 3. 确保连接对话框中的配置符合你的运行环境。 From 69429aff4755f78854329c3f6bd3a877df1e71b0 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 4 Sep 2024 15:49:32 +0800 Subject: [PATCH 011/109] vector-search-overview: refine descriptions --- vector-search-overview.md | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/vector-search-overview.md b/vector-search-overview.md index 00d39d7fd045..ac05ac2a9eef 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -1,48 +1,52 @@ --- title: 向量搜索概述 -summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图像、音频和视频等各种数据类型进行语义搜索。 +summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图像、音频和视频等多种数据类型进行语义搜索。 --- # 向量搜索概述 -TiDB 向量搜索 (beta) 提供了在多种数据类型之间进行语义搜索的高级搜索方案,可以对文档、图像、音频、视频等不同数据类型进行语义上的相似度搜索。TiDB 向量搜索以 MySQL 兼容的 SQL 语法提供,熟悉 MySQL 的开发人员可轻松地基于此构建例如生成式人工智能 (GAI) 应用。 - +TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、图像、音频和视频等多种数据类型之间进行相似度搜索。TiDB 向量搜索的 SQL 语法与 MySQL 兼容,熟悉 MySQL 的开发人员可以基于该功能轻松构建生成式人工智能 (GAI) 应用。 ## 概念 -向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。相比于传统的全文搜索主要依赖于精确的关键词匹配和词频,向量搜索通过将数据(如文本、图像或音频)转换为高维向量,并利用这些向量的相似度进行查询。这种方法能够捕捉数据的语义特征和上下文信息,从而更准确地理解用户意图,即使搜索词语并不完全匹配数据库中的内容。 +向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。 + +与传统的全文搜索(主要依赖于精确的关键词匹配和词频)不同,向量搜索通过将不同类型的数据(如文本、图像或音频)转换为高维向量,并根据这些向量之间的相似度来进行查询。这种搜索方法能够捕捉数据的语义特征和上下文信息,从而更准确地理解用户意图。 -例如,全文搜索 “一种会游泳的动物” 只会返回包含这些精确关键词的结果。相比之下,向量搜索可以返回其他游泳动物的结果,如鱼或鸭子,即使没有准确的关键字。 +即使搜索的词语与数据库中的内容不完全匹配,向量搜索仍然可以通过对数据语义的理解,找到与用户意图相符合的结果。 + +例如,搜索 “一种会游泳的动物” 时,全文搜索只会返回包含这些精确关键词的结果,而向量搜索可以返回其他游泳动物的结果,如鱼或鸭子,即使这些结果并未包含精确的关键词。 ### 向量嵌入 -向量嵌入 (vector embedding) 又称嵌入 (embedding) ,是在高维空间中表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的语义特征和上下文。 +向量嵌入 (vector embedding) 也称为嵌入 (embedding) ,是在高维空间中用于表示现实世界对象的数字序列。它可以捕捉文档、图像、音频和视频等非结构化数据的语义特征和上下文。 向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 -TiDB 引入了[向量数据类型](/vector-search-data-types.md),旨在优化向量嵌入的存储和检索,增强其在人工智能领域的应用。 你可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询以查找最相关的数据。 +TiDB 引入了[向量数据类型](/vector-search-data-types.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询,以找到最相关的数据。 ### 嵌入模型 嵌入模型是将数据转换为[向量嵌入](#向量嵌入)的算法。 -选择合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 +选择一种合适的嵌入模型对于确保语义搜索结果的准确性和相关性至关重要。对于非结构化的文本数据,你可以在 [Massive Text Embedding Benchmark (MTEB) Leaderboard](https://huggingface.co/spaces/mteb/leaderboard) 上找到性能最佳的文本嵌入模型。 -如果你想要了解如何为特定数据类型生成向量嵌入,请参阅嵌入模型的教程或示例。 +如需了解如何为特定数据类型生成向量嵌入,请参阅相关嵌入模型的教程或示例。 -## 向量搜索如何工作 +## 工作原理 -在将原始数据转换为向量并存储在 TiDB 中后,你的应用程序就可以开始执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 +在你将原始数据转换为向量并存储在 TiDB 中后,你的应用程序就可以开始利用这些向量来执行向量搜索查询,找到与用户查询语义或上下文最相关的数据。 -TiDB 向量搜索 (Vector Search) 通过使用 [距离函数](/vector-search-functions-and-operators.md) 来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。与给定向量的距离最小的向量代表最相似的数据。 +TiDB 向量搜索 (Vector Search) 通过使用[距离函数](/vector-search-functions-and-operators.md)来计算给定向量与数据库中存储的向量之间的距离,从而识别前 k 个近邻(KNN)向量。其中,与给定向量距离最小的向量即代表最相似的数据。 ![The Schematic TiDB Vector Search](/media/vector-search/embedding-search.png) -TiDB 是一个支持向量搜索的关系数据库,这意味着你可以在同一个数据库里存储数据和它们的向量表示 (向量嵌入) 。你可以选择把数据和它们的向量放在同一个表里的不同列中,也可以把它们放在不同的表里。在需要搜索的时候,再用 JOIN 查询把这些表的数据组合起来使用。 - + TiDB 作为一款关系型数据库,在引入了向量搜索功能后,支持将数据及其对应的向量表示(向量嵌入)存储在同一个数据库中。你可以选择以下任一种存储方式: +- 将数据和对应的向量表示存储在同一张表的不同列中。 +- 将数据和对应的向量表示分别存储在不同的表中。在进行搜索时,通过 JOIN 查询将这些表关联起来。 -## 使用案例 +## 使用场景 ### 检索增强生成 (Retrieval-Augmented Generation, RAG) @@ -50,11 +54,11 @@ TiDB 是一个支持向量搜索的关系数据库,这意味着你可以在同 ### 语义搜索 -语义搜索是一种根据查询的含义而不是简单地匹配关键词来返回结果的搜索技术。它通过嵌入来解释不同语言和各种类型数据(如文本、图像和音频)的含义。然后,向量搜索算法会使用这些嵌入来查找满足用户查询的最相关数据。 +语义搜索是一种根据查询的含义而不是简单地匹配关键词来返回结果的搜索技术。它将不同语言和各种类型的数据(如文本、图像、音频)的含义转换为向量嵌入。然后,向量搜索算法会使用这些向量嵌入来查找满足用户查询的最相关数据。 ### 推荐引擎 -推荐引擎是一种主动向用户推荐相关和个性化内容、产品或服务的系统。它通过创建代表用户行为和偏好的嵌入来实现这一目标。这些嵌入有助于系统识别其他用户曾与之互动或感兴趣的类似项目。这就增加了推荐与用户相关并吸引用户的可能性。 +推荐引擎是一种推荐系统,它会主动向用户推荐与他们高度相关且个性化的内容、产品或服务。为了实现这一目标,推荐引擎会创建反映用户行为和偏好的向量嵌入。这些嵌入可以帮助系统识别其他用户曾经互动过或感兴趣的类似项目,从而提高推荐内容与用户的相关性,并增加吸引用户的可能性。 ## 另请参阅 From d285b5547670047fa36286b6b7a95bde5a727959 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 4 Sep 2024 17:04:11 +0800 Subject: [PATCH 012/109] vector-search-data-types: refine descriptions --- vector-search-data-types.md | 65 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 25165009e683..3137bcdf4bc9 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -5,27 +5,27 @@ summary: 本文介绍 TiDB 的向量数据类型。 # 向量数据类型 (Vector) -“向量”指的是一组浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。针对 AI 应用中大量使用到的嵌入向量 (Vector Embedding) 数据,TiDB 专门提供了向量类型用于进行高效的存储和访问。 +向量指的是一组浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。针对 AI 应用中大量使用到的嵌入向量 (vector embedding) 数据,TiDB 专门提供了向量数据类型,以便高效地存储和访问这些数据。 -目前有以下几种向量类型: +目前支持的向量数据类型包括: -- `VECTOR`: 存储一组单精度浮点数 (Float) 向量。向量可以是任意维度。 +- `VECTOR`: 存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。 - `VECTOR(D)`: 存储一组单精度浮点数 (Float) 向量,向量维度固定为 `D`。 -相比使用 [`JSON`](/data-type-json.md) 类型,使用向量类型具有以下额外优势: +与使用 [`JSON`](/data-type-json.md) 类型相比,使用向量类型具有以下优势: - 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。 -- 存储格式更优。向量类型针对向量数据进行了特别优化,具有比 `JSON` 类型更高的空间和性能效率。 +- 存储格式更优。向量数据类型针对向量数据进行了特别优化,在空间利用和性能效率上都优于 `JSON` 类型。 ## 语法 -可以使用以下格式的字符串来表示一个类型为向量的值: +可以使用以下格式的字符串来表示一个数据类型为向量的值: ```sql '[, , ...]' ``` -例如: +示例: ```sql CREATE TABLE vector_table ( @@ -38,22 +38,21 @@ 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,因此插入不同其他维度的向量数据会引发错误: +前面的示例中 `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-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 ## 混合存储不同维度的向量 @@ -71,33 +70,33 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, ## 比较 -[比较运算符](/vector-search-functions-and-operators.md) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解所有支持向量类型的函数和操作符。 +[比较运算符](/vector-search-functions-and-operators.md) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 -比较向量类型时,TiDB 以向量内的各个元素为单位进行依次比较,如: +比较向量数据类型时,TiDB 会以向量中的各个元素为单位进行依次比较,如: - `[1] < [12]` - `[1,2,3] < [1,2,5]` - `[1,2,3] = [1,2,3]` - `[2,2,3] > [1,2,3]` -当两个向量维度不一样时,TiDB 采用字典序 (Lexicographical Order) 进行比较,具体规则如下: +当两个向量的维度不同时,TiDB 采用字典序 (Lexicographical Order) 进行比较,具体规则如下: -- 两个向量内各个元素逐一进行数值比较。 -- 遇到第一个不一样的元素时,它们之间的数值比较结果即是两个向量之间的比较结果。 +- 两个向量中的各个元素逐一进行数值比较。 +- 当遇到第一个不同的元素时,它们之间的数值比较结果即为两个向量之间的比较结果。 - 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。 - 长度相同且各个元素相同的两个向量 _相等_ 。 - 空向量 _小于_ 任何非空向量。 - 两个空向量 _相等_ 。 -例如: +示例: - `[] < [1]` - `[1,2,3] < [1,2,3,0]` -在进行向量比较时,可以使用 [显式转换](#类型转换-cast) 将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: +在进行向量比较时,请使用[显式转换](#类型转换-cast)将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: ```sql --- 因为给出的实际上是字符串,因此 TiDB 会按字符串进行比较 +-- 因为给出的数据实际上是字符串,因此 TiDB 会按字符串进行比较 [tidb]> SELECT '[12.0]' < '[4.0]'; +--------------------+ | '[12.0]' < '[4.0]' | @@ -106,7 +105,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, +--------------------+ 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]') | @@ -118,7 +117,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, ## 运算 -向量类型支持算术运算 `+` 和 `-`,对应的是两个向量进行以元素为单位的加法和减法。不支持对不同维度向量进行算术运算,这类运算会产生错误。 +向量数据类型支持算术运算 `+` 和 `-`,对应的是两个向量以元素为单位进行的加法和减法。不支持对不同维度向量进行算术运算,执行这类运算会遇到报错。 以下是一些示例: @@ -149,12 +148,12 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 可以使用以下函数在向量和字符串之间进行转换: -- `CAST(... AS VECTOR)`: String ⇒ Vector -- `CAST(... AS CHAR)`: Vector ⇒ String -- `VEC_FROM_TEXT`: String ⇒ Vector -- `VEC_AS_TEXT`: Vector ⇒ String +- `CAST(... AS VECTOR)`: 将 String 类型转换为 Vector 类型 +- `CAST(... AS CHAR)`: 将 Vector 类型转换为 String 类型 +- `VEC_FROM_TEXT`: 将 String 类型转换为 Vector 类型 +- `VEC_AS_TEXT`: 将 Vector 类型转换为 String 类型 -出于易用性考虑,若函数只支持向量数据类型(如向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: +出于易用性考虑,如果你使用的函数只支持向量数据类型(例如,向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: ```sql -- VEC_DIMS 只接受向量类型,因此你可以直接传入字符串类型,TiDB 会隐式转换为向量类型: @@ -185,7 +184,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -当运算符或函数接受多种数据类型时,隐式转换不会发生,请先显式地将字符串类型转换为向量类型后,再传递给这些运算符或函数。例如,进行比较运算前,需要显式地转换字符串为向量类型,否则将会按照字符串类型进行比较,而非按照向量类型进行比较: +当你使用的运算符或函数接受多种数据类型时,TiDB 不会进行隐式转换,请先显式地将字符串类型转换为向量类型后,再传递给这些运算符或函数。例如,进行比较运算前,需要显式地将字符串转换为向量类型,否则 TiDB 将会按照字符串类型进行比较,而非按照向量类型进行比较: ```sql -- 传入的类型是字符串,因此 TiDB 会按字符串进行比较: @@ -207,10 +206,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -向量也可以显式地转换为字符串。可使用 `VEC_AS_TEXT()` 函数: +向量也可以显式地转换为字符串。以使用 `VEC_AS_TEXT()` 函数为例: ```sql --- 字符串首先被隐式地转换成向量,然后被显示地转为字符串,因而获得了一个规范化的格式: +-- 字符串首先被隐式地转换成向量,然后被显示地转为字符串,因而返回了一个规范化的字符串格式: [tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); +--------------------------------------+ | VEC_AS_TEXT('[0.3, 0.5, -0.1]') | @@ -220,19 +219,19 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 1 row in set (0.01 sec) ``` -若要了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 +如需了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 ### 向量与其他数据类型之间的转换 -目前无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以使用字符串作为中间类型进行转换。 +目前 TiDB 无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以使用字符串作为中间类型进行转换。 -## 约束 +## 使用限制 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 - 目前向量类型只支持单精度浮点数,不支持双精度浮点数。未来版本将支持这一功能。 -有关其他限制,请参阅 [向量搜索限制](/vector-search-limitations.md)。 +有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 ## MySQL 兼容性 From 3852ed38ade94665f579292d0f0d9880784fdf31 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 4 Sep 2024 18:12:27 +0800 Subject: [PATCH 013/109] vector-search-functions-and-operators: refine descriptions --- vector-search-functions-and-operators.md | 117 ++++++++++++----------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 518fd182f51b..dbba4cea8a20 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -5,23 +5,24 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 # 向量函数和操作符 +本文介绍 TiDB 支持的向量函数和操作符。 ## 向量函数 -TiDB 为 [向量数据类型](/vector-search-data-types.md) 设计了以下函数: +TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量函数: -**向量距离函数:** +**向量距离函数** -| Function Name | Description | +| 函数名 | 描述 | | --------------------------------------------------------- | ----------------------------------------------------------- | | [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 距离 (曼哈顿距离) | -**其他向量函数:** +**其他向量函数** -| Function Name | Description | +| 函数名 | Description | | ------------------------------- | --------------------------------------------------- | | [VEC_DIMS](#vec_dims) | 返回向量的维度 | | [VEC_L2_NORM](#vec_l2_norm) | 返回向量的 L2 范数 (欧氏规范) | @@ -30,68 +31,68 @@ TiDB 为 [向量数据类型](/vector-search-data-types.md) 设计了以下函 ## 扩展的内置函数和运算符 -TiDB 扩展了以下内置函数和运算符,它们额外也支持[向量数据类型](/vector-search-data-types.md)。 +TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运算符也支持[向量数据类型](/vector-search-data-types.md)。 -**算术运算符:** +**算术运算符** -| Name | Description | +| 运算符 | 描述 | | :-------------------------------------------------------------------------------------- | :--------------------------------------- | | [`+`](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#运算)。 +关于向量运算工作原理的更多信息,请参阅[向量数据类型的运算](/vector-search-data-types.md#运算)。 -**聚合函数 (GROUP BY) :** +**聚合函数 (GROUP BY)** -| Name | Description | +| 函数名 | 描述 | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | [`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) | 返回最小值 | -**比较函数与操作符:** +**比较函数与操作符** -| Name | Description | +| 名称 | 描述 | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | [`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) | 获得第一个非空参数 | -| [`=`](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) | 安全的等于运算符 | +| [`=`](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) | 空值安全相等比较符 | | [`>`](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) | 获得最大参数 | +| [`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) | 获得最小参数 | +| [`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#比较)。 +关于如何比较向量的更多信息,请参阅[向量数据类型的比较](/vector-search-data-types.md#比较)。 -**控制流函数:** +**控制流程函数** -| Name | Description | +| 函数名 | 描述 | | :------------------------------------------------------------------------------------------------ | :--------------------------- | | [`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 | +| [`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` | -**转换函数:** +**转换函数** -| Name | Description | +| 函数名 | 描述 | | :------------------------------------------------------------------------------------------ | :----------------------------- | | [`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)。 +关于如何使用 `CAST()` 的更多信息,请参阅[向量数据类型的转换](/vector-search-data-types.md#类型转换-cast)。 -## 函数使用样例 +## 使用示例 ### VEC_L2_DISTANCE @@ -99,16 +100,16 @@ TiDB 扩展了以下内置函数和运算符,它们额外也支持[向量数 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) 距离,你可以使用以下公式: +该函数用于计算两个向量之间的 [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]'); +[tidb]> SELECT VEC_L2_DISTANCE('[0,3]', '[4,0]'); +-----------------------------------+ | VEC_L2_DISTANCE('[0,3]', '[4,0]') | +-----------------------------------+ @@ -122,16 +123,16 @@ $DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ 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) 距离,你可以使用以下公式: +该函数用于计算两个向量之间的[余弦 (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]'); +[tidb]> SELECT VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]'); +-------------------------------------------+ | VEC_COSINE_DISTANCE('[1, 1]', '[-1, -1]') | +-------------------------------------------+ @@ -145,16 +146,16 @@ $DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \ VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2) ``` -要计算两个向量之间的 [内积](https://zh.wikipedia.org/wiki/%E7%82%B9%E7%A7%AF) 的负值,你可以使用以下公式: +该函数用于计算两个向量之间[内积](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]'); +[tidb]> SELECT VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]'); +----------------------------------------------+ | VEC_NEGATIVE_INNER_PRODUCT('[1,2]', '[3,4]') | +----------------------------------------------+ @@ -168,16 +169,16 @@ $DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ 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) (曼哈顿距离),你可以使用以下公式: +该函数用于计算两个向量之间的 [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]'); +[tidb]> SELECT VEC_L1_DISTANCE('[0,0]', '[3,4]'); +-----------------------------------+ | VEC_L1_DISTANCE('[0,0]', '[3,4]') | +-----------------------------------+ @@ -191,19 +192,19 @@ $DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ VEC_DIMS(vector) ``` -要计算给定向量的维度,你可以使用以下语句: +该函数返回给定向量的维度。 -例如: +示例: ```sql -[tidb]> select VEC_DIMS('[1,2,3]'); +[tidb]> SELECT VEC_DIMS('[1,2,3]'); +---------------------+ | VEC_DIMS('[1,2,3]') | +---------------------+ | 3 | +---------------------+ -[tidb]> select VEC_DIMS('[]'); +[tidb]> SELECT VEC_DIMS('[]'); +----------------+ | VEC_DIMS('[]') | +----------------+ @@ -217,14 +218,14 @@ VEC_DIMS(vector) VEC_L2_NORM(vector) ``` -要计算给定向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0) (欧几里得范数),可以使用以下公式: +该函数用于计算给定向量的 [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]'); +[tidb]> SELECT VEC_L2_NORM('[3,4]'); +----------------------+ | VEC_L2_NORM('[3,4]') | +----------------------+ @@ -238,12 +239,12 @@ $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ VEC_FROM_TEXT(string) ``` -要将字符串类型转换为向量类型,可以使用以下语句: +该函数用于将字符串类型转换为向量类型。 -例如: +示例: ```sql -[tidb]> select VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]'); +[tidb]> SELECT VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]'); +-------------------------------------------------+ | VEC_FROM_TEXT('[1,2]') + VEC_FROM_TEXT('[3,4]') | +-------------------------------------------------+ @@ -257,12 +258,12 @@ VEC_FROM_TEXT(string) VEC_AS_TEXT(vector) ``` -要将向量类型转换为字符串类型,可以使用以下语句: +该函数用于将向量类型转换为字符串类型。 -例如: +示例: ```sql -[tidb]> select VEC_AS_TEXT('[1.000, 2.5]'); +[tidb]> SELECT VEC_AS_TEXT('[1.000, 2.5]'); +-------------------------------+ | VEC_AS_TEXT('[1.000, 2.5]') | +-------------------------------+ From 93b7e905e057523c3747fd1b8f5eb15c5c94dbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 5 Sep 2024 16:49:34 +0800 Subject: [PATCH 014/109] add remaining doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-changelogs.md | 15 + vector-search-get-started-using-python.md | 2 +- ...-search-integrate-with-jinaai-embedding.md | 279 ++++++++ vector-search-integrate-with-langchain.md | 622 ++++++++++++++++++ vector-search-integrate-with-llamaindex.md | 300 +++++++++ vector-search-integration-overview.md | 67 ++ 6 files changed, 1284 insertions(+), 1 deletion(-) create mode 100644 vector-search-changelogs.md create mode 100644 vector-search-integrate-with-jinaai-embedding.md create mode 100644 vector-search-integrate-with-langchain.md create mode 100644 vector-search-integrate-with-llamaindex.md create mode 100644 vector-search-integration-overview.md diff --git a/vector-search-changelogs.md b/vector-search-changelogs.md new file mode 100644 index 000000000000..2cb548e1910c --- /dev/null +++ b/vector-search-changelogs.md @@ -0,0 +1,15 @@ +--- +title: 向量搜索更新日志 + +summary: 了解 TiDB 向量搜索功能的新功能、兼容性更改、改进和错误修复。 +--- + +# 向量搜索更新日志 + +## 2024 年 6 月 25 日 + +- TiDB Vector Search(测试版)现在适用于所有地区的所有用户的 TiDB Serverless 集群。 + +## 2024 年 4 月 1 日 + +- TiDB Vector Search(测试版)现适用于欧洲地区受邀用户的 TiDB Serverless 集群。 \ No newline at end of file diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index c1c22c50abf4..20345e40c21e 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -1,5 +1,5 @@ --- -title: 使用Python开始向量搜索 +title: 使用 Python 开始向量搜索 summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语义搜索的人工智能应用程序。 --- diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md new file mode 100644 index 000000000000..c976c2535307 --- /dev/null +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -0,0 +1,279 @@ +--- +title: 结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索 +summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索,以存储向量嵌入信息并执行语义搜索。 +--- + +# 结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索 + +本文档将展示如何使用 [Jina AI](https://jina.ai/) 为文本数据生成向量嵌入,然后将向量嵌入存储在 TiDB 中,并根据向量嵌入搜索相似文本。 + +## 前置需求 + +To complete this tutorial, you need: + +- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 +- [Git](https://git-scm.com/downloads)。 +- TiDB 集群,如果你还没有 TiDB 集群,可以按照以下方式创建: + - TiDB Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 + - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 + +## 运行示例程序 + +您可以通过以下步骤快速了解如何结合 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. 配置环境变量 + +#### 4.1 获取 Jina AI API 密钥 + +从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥。 + + + +
+ +#### 4.2 获取 TiDB 连接参数 + +1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 + +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**生成一个随机密码。 + +#### 4.3 设置环境变量 + +在终端中设置环境变量,或创建一个包含上述环境变量的 `.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" +``` + +
+ +
+ +#### 4.2 设置 TiDB 连接参数 + +- 创建一个包含如下环境变量的 `.env` 文件: + - TIDB_HOST='{host}' + - TIDB_PORT='4000' + - TIDB_USER='root' + - TIDB_PASSWORD='{password}' + - TIDB_DB_NAME='test' + + 注意替换 {} 中的占位符为你的 TiDB 对应的值,并删除 CA_PATH 这行。如果你在本机运行 TiDB,默认 Host 地址为 127.0.0.1,密码为空。 + +- 在终端中设置环境变量 + + ```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" + ``` + 注意替换为你的 TiDB 实际对应的值。 +
+ +
+ +### 步骤 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 Serverless + +通过 SQLAlchemy 连接 TiDB Serverless: + +```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), + comment="hnsw(distance=cosine)" +``` + +> **Note:** +> +> - 向量列的维度必须与嵌入模型生成的向量嵌入维度相匹配。 +> - 在本例中,`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: + # Generate embeddings for the texts via 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 生成查询文本的向量嵌入,然后根据查询向量嵌入和文档向量嵌入之间的余弦距离搜索最相关的文档: + +```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) \ 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..e686506d844c --- /dev/null +++ b/vector-search-integrate-with-langchain.md @@ -0,0 +1,622 @@ +--- +title: 在 LangChain 中使用 TiDB 向量搜索 +summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 +--- + +# 在 LangChain 中使用 TiDB 向量搜索 + +本文档展示如何在 [LangChain](https://python.langchain.com/) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 + +> **Note** +> +> - 您可以在 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 Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 + - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 + +## 开始 + +本节将逐步说明如何在 LangChain 中使用 TiDB 向量搜索进行语义搜索。 + +### 步骤 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. 设置环境 + + +
+ +#### 步骤 3.1 获取 TiDB 群集的连接字符串 + + 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**Connect**。此时将显示连接对话框。 + + 3. 确保连接对话框中的配置符合您的运行环境。 + + - **Connection Type** 设置为 `Public`. + - **Branch** 设置为 `main`. + - **Connect With** 设置为 `SQLAlchemy`. + - **Operating System** 与你的系统环境相匹配. + + 4. 点击 **PyMySQL** 标签,复制连接字符串。 + + > **Tip:** + > + > 如果尚未设置密码,请单击**Generate Password**生成一个随机密码。 + +#### 步骤 3.2 配置环境变量 + +要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 + +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [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:") +``` + +
+ +
+ +#### 步骤 3.1 配置环境变量 + +要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 + +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [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://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` +注意替换为你的 TiDB 实际对应的值。 + +
+ +
+ +### 步骤 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" +``` + +#### 选项 1:使用 `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) +``` + +
+ Expected output + +```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. +-------------------------------------------------------------------------------- +``` + +
+ +#### 选项 2:使用 `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) +``` + +
+ Expected output + +```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() +``` + +## 使用元数据过滤器搜索 + +To refine your searches, you can use metadata filters to retrieve specific nearest-neighbor results that match the applied filters. + +你可以使用元数据过滤器来检索与所应用的过滤器相匹配的特定近邻结果,以进一步改进搜索。 + +### 支持的元数据类型 + +TiDB 向量存储中的每个文档都可以与元数据配对,元数据的结构是 JSON 对象中的键值对。键的类型一般是字符串,而值可以是以下任何类型: + +- 字符串 +- 数值: integer 或 floating point +- 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 }] +} +``` + +元数据过滤器中的每个键值对都被视为一个单独的过滤器子句,这些子句使用 `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) \ 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..93c09bea3a86 --- /dev/null +++ b/vector-search-integrate-with-llamaindex.md @@ -0,0 +1,300 @@ +--- +title: 在 LlamaIndex 中使用 TiDB 向量搜索 +summary: 展示如何在 LlamaIndex 中使用 TiDB 向量搜索 +--- + +# 在 LlamaIndex 中使用 TiDB 向量搜索 + +本文档展示如何在 [LlamaIndex](https://www.llamaindex.ai) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 + +> **Note** +> +> - 您可以在 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 Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 + - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 + +## 开始 + +本节将逐步说明如何在 LlamaIndex 中使用 TiDB 向量搜索进行语义搜索。 + +### 步骤 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. 设置环境 + + + +
+ +#### 步骤 3.1 获取 TiDB 群集的连接字符串 + + 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 + + 2. 单击右上角的**Connect**。此时将显示连接对话框。 + + 3. 确保连接对话框中的配置符合您的运行环境。 + + - **Connection Type** 设置为 `Public`. + - **Branch** 设置为 `main`. + - **Connect With** 设置为 `SQLAlchemy`. + - **Operating System** 与你的系统环境相匹配. + + 4. 点击 **PyMySQL** 标签,复制连接字符串。 + + > **Tip:** + > + > 如果尚未设置密码,请单击**Generate Password**生成一个随机密码。 + +#### 步骤 3.2 配置环境变量 + +要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 + +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [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:") +``` + +
+ +
+ +#### 步骤 3.1 配置环境变量 + +要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 + +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [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://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` +注意替换为你的 TiDB 实际对应的值。 + +
+ +
+ +### 步骤 4. 加载样本文件 + +#### 步骤 4.1 下载样本文件 + +在项目目录中创建名为 `data/paul_graham/` 的目录,并从 [run-llama/llama_index](https://github.com/run-llama/llama_index) 代码库中下载示例文档 [`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)) +``` + +> **Note** +> +> `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) \ 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..af69efdfe760 --- /dev/null +++ b/vector-search-integration-overview.md @@ -0,0 +1,67 @@ +--- +title: 向量搜索集成概述 +summary: TiDB 向量搜索集成概述,包括支持的 AI 框架、嵌入模型和 ORM 库。 +--- + +# 向量搜索集成概述 + +本文档概述了 TiDB 向量搜索集成,包括支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 + +## 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 完成其他需求,例如用于 AI 应用的文档存储和知识图谱存储等。 + +## 嵌入模型和服务 + +TiDB 向量搜索支持存储多达 16,383 维的向量,可适应大多数嵌入模型。 + +你可以使用自行部署的开源嵌入模型或第三方嵌入模型提供商的嵌入 API 来生成向量。 + +下表列出了一些主流嵌入模型服务提供商和相应的集成教程。 + +| 嵌入模型服务提供商 | 教程 | +|-----------------------------|---------------------------------------------------------------------------------------------------------------------| +| Jina AI | [通过Jina AI 嵌入 API 使用向量搜索](/vector-search-integrate-with-jinaai-embedding.md) | + +## 对象关系映射 (ORM) 库 + +你可以通过结合 ORM 库使用 TiDB 向量搜索,以便与 TiDB 数据库交互。 + +下表列出了支持的 ORM 库和相应的使用教程: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LanguageORM/ClientHow to installTutorial
PythonTiDB Vector Clientpip install tidb-vector[client]使用 Python 开始向量搜索
SQLAlchemypip install tidb-vectorTiDB 向量搜索在 SQLAlchemy 中的使用
peeweepip install tidb-vectorTiDB 向量搜索在 peewee 中的使用
Djangopip install django-tidb[vector]TiDB 向量搜索在 Django 中的使用
\ No newline at end of file From 15e18d0cf70b0a206bf0d6a714d26a0952e4d5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 5 Sep 2024 16:52:43 +0800 Subject: [PATCH 015/109] remove rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-integrate-with-jinaai-embedding.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index c976c2535307..1f1c97fb9529 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -9,8 +9,6 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, ## 前置需求 -To complete this tutorial, you need: - - 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 - [Git](https://git-scm.com/downloads)。 - TiDB 集群,如果你还没有 TiDB 集群,可以按照以下方式创建: From 402f1d0dbeb68e9154940fb7bb6e2086b51897ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 5 Sep 2024 17:02:00 +0800 Subject: [PATCH 016/109] fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-integrate-with-llamaindex.md | 1 + 1 file changed, 1 insertion(+) diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 93c09bea3a86..9865f198c1f3 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -117,6 +117,7 @@ import os tidb_connection_string = getpass.getpass("TiDB Connection String:") os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") ``` + 例如,macOS 上的连接字符串如下所示: ```dotenv From f869c426ac98a8d86bbc08d5b856b4a433e91555 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Thu, 5 Sep 2024 18:08:32 +0800 Subject: [PATCH 017/109] get started: refine descriptions --- vector-search-get-started-using-python.md | 149 +++++++++++----------- vector-search-get-started-using-sql.md | 77 ++++++----- 2 files changed, 117 insertions(+), 109 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index c1c22c50abf4..c91a9f9081e4 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -5,31 +5,30 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 # 使用 Python 开始向量搜索 -本文展示如何开发一个简单的 AI 应用,这个 AI 应用实现了简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以智能地“理解”你的输入,返回更相关的结果。例如,在“狗”、“鱼”和“树”这三个内容中搜索“一种会游泳的动物”时,语义搜索会将“鱼”作为最相关的结果。 +本文将展示如何开发一个简单的 AI 应用,这个 AI 应用实现了简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以智能地理解你的输入,返回更相关的结果。例如,在“狗”、“鱼”和“树”这三条内容中搜索“一种会游泳的动物”时,语义搜索会将“鱼”作为最相关的结果返回。 -在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型构建 AI 应用。 +在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型完成这个 AI 应用的开发。 +## 前置需求 -## 准备 -在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -- TiDB Serverless 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 +为了能够顺利完成本文中的操作,你需要提前: -- 本地部署的 TiDB 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: -## 开始 +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -以下是从零构建这个应用的详细步骤,你也可以从 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 开源代码库获取到完整代码,直接运行示例。 +## 快速开始 -### 步骤 1. 创建一个新的 Python 项目 +以下为从零开始构建这个应用的详细步骤,你也可以从 [pingcap/tidb-vector-python](https://github.com/pingcap/tidb-vector-python/blob/main/examples/python-client-quickstart) 开源代码库获取到完整代码,直接运行示例。 -创建一个新 Python 项目和一个名为 `example.py` 的文件: +### 第 1 步:新建一个 Python 项目 + +在你的本地目录中,新建一个 Python 项目和一个名为 `example.py` 的文件: ```shell mkdir python-client-quickstart @@ -37,77 +36,79 @@ cd python-client-quickstart touch example.py ``` -### 步骤 2. 安装所需的依赖项 +### 第 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 集群的连接字符串 -1. 根据不同的 TiDB 集群部署方式,配置集群的连接字符串 - - -
+- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成[向量嵌入](/vector-search-overview.md#向量嵌入)。 - 1. 在 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 +### 第 3 步:配置 TiDB 集群的连接字符串 - 2. 单击右上角的**Connect**。此时将显示连接对话框。 +根据不同的 TiDB 集群部署方式,配置集群的连接字符串 - 3. 检查连接对话框中的配置,根据你的运行环境为其设置相应的值。 + - - **Endpoint Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `SQLAlchemy`. - - **Operating System** 与机器环境相匹配. +
- > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 - 4. 单击 **PyMySQL** 标签,复制连接字符串。 +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 - > **Tip:** - > - > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 +3. 确认对话框中的配置和你的运行环境一致。 - 5. 在 Python 项目的根目录下创建一个 `.env` 文件,将连接字符串粘贴到其中。 + - **Endpoint Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `SQLAlchemy`。 + - **Operating System** 为你的运行环境。 - 以下是 MacOS 的示例: + > **Tip:** + > + > 如果你的项目在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 - ```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. 单击 **PyMySQL** 选项卡,复制连接字符串。 -
+ > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 -
- - 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 +5. 在 Python 项目的根目录下新建一个 `.env` 文件,将连接字符串粘贴到其中。 - - `HOST`: TiDB 集群的主机号。 - - `PORT`: TiDB 集群的端口。 - - `USERNAME`: 连接 TiDB 集群的用户名。 - - `PASSWORD`: 连接 TiDB 集群的密码。 - - `DATABASE`: 要连接的数据库名称。 - - `CA_PATH`: 根证书文件的路径。 - - 以下是 MacOS 的示例: + 以下为 MacOS 的示例: ```dotenv - TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + 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" ``` -
-
+
+ +
+ +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 + +- `HOST`:TiDB 集群的主机号。 +- `PORT`:TiDB 集群的端口。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。 +- `CA_PATH`:根证书文件的路径。 + +以下是 MacOS 的示例: + +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` + +
+
-### 步骤 4. 初始化嵌入模型 +### 第 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 维向量嵌入。 +[嵌入模型](/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()` 函数用于将文本数据转换为向量数据。 @@ -124,13 +125,13 @@ def text_to_embedding(text): return embedding.tolist() ``` -### 步骤 5. 连接到 TiDB 集群 +### 第 5 步:连接到 TiDB 集群 -使用 `TiDBVectorClient` 类连接到 TiDB 集群,并创建一个带有向量列的表 `embedded_documents` 。 +使用 `TiDBVectorClient` 类连接到 TiDB 集群,并创建一个包含向量列的表 `embedded_documents`。 > **Note** > -> 创建的表中,向量列的维度需要与嵌入模型生成的向量维度一致。如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度, `embedded_documents` 的向量列维度也为384。 +> 请确保你创建的表中向量列的维度与嵌入模型生成的向量维度一致。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度, `embedded_documents` 的向量列维度也应为 384。 ```python import os @@ -141,20 +142,20 @@ from dotenv import load_dotenv load_dotenv() vector_store = TiDBVectorClient( - # embedded_documents表存储向量数据 + # embedded_documents 表将用于存储向量数据 table_name='embedded_documents', - # TiDB 集群的连接字符串。 + # 指定 TiDB 集群的连接字符串 connection_string=os.environ.get('TIDB_DATABASE_URL'), - # 嵌入模型生成的向量的维度。 + # 指定嵌入模型生成的向量的维度 vector_dimension=embed_model_dims, - # 如果表已经存在,则重新创建该表。 + # 如果表已经存在,则重新创建该表 drop_existing_table=True, ) ``` -### 步骤 6. 向 **embedded_documents** 表中插入数据 +### 第 6 步:将文本数据转换为向量嵌入,并向表中插入数据 -你需要准备好文本数据,比如 “狗”、“鱼 ”和 “树”。 以下代码使用 `text_to_embedding()` 函数将这些文本数据转换为向量嵌入,然后将向量嵌入插入到 `embedded_documents` 表中。 +准备一些文本数据,比如 `"dog"`、`"fish"` 和 `"tree"`。以下代码将使用 `text_to_embedding()` 函数将这些文本数据转换为向量嵌入,然后将向量嵌入插入到 `embedded_documents` 表中: ```python documents = [ @@ -186,9 +187,9 @@ vector_store.insert( ) ``` -### 步骤 7. 执行语义搜索 +### 第 7 步:执行语义搜索 -在这一步中,假如你查询与现有文档中的任何单词都不匹配的内容,比如: “一种会游泳的动物”。 +查询一个与 `documents` 中的任何单词都不匹配的关键词,比如 "a swimming animal"。 以下的代码会再次使用 `text_to_embedding()` 函数将查询文本转换为向量嵌入,然后使用该嵌入进行查询,找出最匹配的前三个词。 @@ -213,9 +214,9 @@ Search result ("a swimming animal"): - text: "tree", distance: 0.798545178640937 ``` -从输出结果来看,会游泳的动物很可能是一条鱼,或者是一只有游泳天赋的狗。 +搜索结果中的 3 个词会按向量的远近排列:距离越小,对应的 `document` 越相关。 -本文展示了向量搜索如何高效地找到最相关的文档,搜索结果按向量的远近排列:距离越小,文档越相关。 +因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 ## 另请参阅 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index b1f0e0700b68..d14a9b5a21d4 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -1,72 +1,77 @@ --- -title: 使用SQL开始向量搜索 +title: 使用 SQL 开始向量搜索 summary: 了解如何使用 SQL 语句快速开始使用 TiDB Cloud 中的向量搜索,并为生成式人工智能应用提供动力。 --- -# 使用SQL开始向量搜索 +# 使用 SQL 开始向量搜索 -TiDB 扩展了 MySQL 语法以支持 [向量搜索](/vector-search-overview.md),并引入了新的 [向量数据类型](/vector-search-data-types.md) 和多个 [向量函数](/vector-search-functions-and-operators.md)。 +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): +本文将展示如何使用 SQL 语句在 TiDB 中进行向量搜索。在本文中,你将使用 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)完成以下任务: -- 连接到 TiDB 集群。 +- 连接到 TiDB 集群 - 创建向量表 - 存储向量嵌入 - 执行向量搜索查询 -## 准备 -在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -- TiDB Serverless 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 +## 前置需求 -- 本地部署的 TiDB 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [MySQL 命令行客户端](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) (MySQL CLI) +- 准备一个 TiDB 集群 + +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: + +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -## 开始 +## 快速开始 -### 步骤 1. 连接到 TiDB 集群 +### 第 1 步:连接到 TiDB 集群 + +根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 将连接命令输入至终端。以下是 macOS 的示例: + - TiDB Serverless 集群 + ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' ``` - 本地部署的 TiDB 集群 + ```bash mysql --comments --host 127.0.0.1 --port 4000 -u root ``` -### 步骤 2. 创建向量表 +### 第 2 步:创建向量表 -TiDB 支持了向量搜索,允许用户在创建表时使用 `VECTOR` 声明 [向量](/vector-search-overview.md#向量嵌入) 列。 +在建表时,你可以使用 `VECTOR` 数据类型声明指定列为[向量](/vector-search-overview.md#向量嵌入)列。 -要创建带有三维 `VECTOR` 列的表,你可以使用 MySQL CLI 执行以下 SQL 语句: +例如,如需创建一张带有三维 `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. 向表中插入向量 +### 第 3 步:向表中插入向量 -将三行附带 [向量](/vector-search-overview.md#向量嵌入) 的数据及其 插入 `embedded_documents` 表: +向 `embedded_documents` 表中插入三行包含[向量](/vector-search-overview.md#向量嵌入)的数据: ```sql INSERT INTO embedded_documents @@ -76,7 +81,7 @@ VALUES (3, 'tree', '[1,0,0]'); ``` -预期输出如下 +预期输出如下: ``` Query OK, 3 rows affected (0.15 sec) @@ -87,17 +92,17 @@ Records: 3 Duplicates: 0 Warnings: 0 > > 为了方便展示,本示例简化了向量的维数,仅使用三维向量。 > -> 在实际应用中,[嵌入模型](/vector-search-overview.md#嵌入模型) 通常会产生数百或数千维的向量。 +> 在实际应用中,[嵌入模型](/vector-search-overview.md#嵌入模型)通常会生成数百或数千维的向量。 -### 步骤 4. 查询向量表 +### 第 4 步:查询向量表 -要验证文件是否已正确插入,你可以查询 `embedded_documents` 表: +要验证上一步中的三行数据是否已正确插入,可以查询 `embedded_documents` 表: ```sql SELECT * FROM embedded_documents; ``` -预期输出如下 +预期输出如下: ```sql +----+----------+-----------+ @@ -110,13 +115,13 @@ SELECT * FROM embedded_documents; 3 rows in set (0.15 sec) ``` -### 步骤 5. 执行向量搜索查询 +### 第 5 步:执行向量搜索查询 与全文搜索类似,在使用向量搜索时,你需要指定搜索词。 -在本例中,搜索词是 “一种会游泳的动物”,其对应的向量是 `[1,2,3]`。在实际应用中,需要使用嵌入模型将用户的搜索词转换为向量。 +在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用嵌入模型将用户的搜索词转换为向量。 -在以下执行的 SQL 语句中,TiDB 会计算 `[1,2,3]` 与表中向量的余弦距离 (`vec_cosine_distance`),然后进行排序输出表中最接近搜索向量 (余弦距离最小) 的前三个向量。 +执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量 (余弦距离最小) 的前三个向量。 ```sql SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance @@ -125,7 +130,7 @@ ORDER BY distance LIMIT 3; ``` -预期输出如下 +预期输出如下: ```plain +----+----------+---------------------+ @@ -138,7 +143,9 @@ LIMIT 3; 3 rows in set (0.15 sec) ``` -从输出结果来看,会游泳的动物很可能是 “一条鱼” ,或者是一只 “有游泳天赋的狗”。 +搜索结果中的 3 个词会按向量的远近排列:距离越小,对应的 `document` 越相关。 + +因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 ## 另请参阅 From ea2b0b1ac4c3047e27e4f74b6bddfca713c2deb5 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 6 Sep 2024 14:22:40 +0800 Subject: [PATCH 018/109] integrate-with-django-orm: refine descriptions --- vector-search-get-started-using-python.md | 4 +- vector-search-integrate-with-django-orm.md | 159 +++++++++++---------- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index cec5e6946f38..f031d9480981 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -68,7 +68,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv > **Tip:** > - > 如果你的项目在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 4. 单击 **PyMySQL** 选项卡,复制连接字符串。 @@ -97,7 +97,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv - `DATABASE`:要连接的数据库名称。 - `CA_PATH`:根证书文件的路径。 -以下是 MacOS 的示例: +以下为 MacOS 的示例: ```dotenv TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index ec19dce63443..278c75e89e52 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -1,30 +1,30 @@ --- title: TiDB 向量搜索在 Django ORM 中的使用 -summary: 了解如何在 Django ORM 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 +summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 --- # TiDB 向量搜索在 Django ORM 中的使用 本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 -## 准备 -在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -- TiDB Serverless 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 +## 前置需求 -- 本地部署的 TiDB 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: +- 在你的机器上安装 [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 Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 你可以通过以下步骤快速了解如何在 Django ORM 中使用 TiDB 向量搜索。 -### 步骤 1. 克隆仓库 +### 第 1 步:克隆示例代码仓库 将 `tidb-vector-python` 仓库克隆到本地: @@ -32,9 +32,9 @@ summary: 了解如何在 Django ORM 中 TiDB 使用向量搜索,,以存储 git clone https://github.com/pingcap/tidb-vector-python.git ``` -### 步骤 2. 创建虚拟环境 +### 第 2 步:创建虚拟环境 -为项目创建虚拟环境: +为你的项目创建虚拟环境: ```bash cd tidb-vector-python/examples/orm-django-quickstart @@ -42,9 +42,9 @@ python3 -m venv .venv source .venv/bin/activate ``` -### 步骤 3. 安装所需的依赖项 +### 第 3 步:安装所需的依赖 -安装示例项目所需的依赖项: +安装示例项目所需的依赖: ```bash pip install -r requirements.txt @@ -60,77 +60,78 @@ pip install Django django-tidb mysqlclient numpy python-dotenv #### 什么是 `django-tidb`? -`django-tidb`使用 django 框架提供了与 tidb 交互的示例,它实现了 Django ORM 以支持 TiDB 的向量搜索,并解决了 TiDB 和 Django 之间的兼容性问题。 +`django-tidb` 是一个为 Django 提供的 TiDB 适配器。通过该适配器,Django ORM 实现了对 TiDB 特有的功能(如,向量搜索)的支持,并解决了 TiDB 和 Django 之间的兼容性问题。 -要安装 `django-tidb`,请选择与 Django 版本相匹配的版本。例如,如果使用的是 `django==4.2.*`, 则安装 `django-tidb===4.2.*`。次版本号不必相同,但建议使用最新的次版本。 +安装 `django-tidb` 时,请选择与你的 Django 版本相匹配的版本。例如,如果你使用的是 `django==4.2.*`, 则应安装 `django-tidb===4.2.*`,其中 minor 版本号不需要完全相同。建议使用最新的 minor 版本。 -更多信息,请参阅 [django-tidb repository](https://github.com/pingcap/django-tidb)。 +更多信息,请参考 [django-tidb 仓库](https://github.com/pingcap/django-tidb)。 -### 步骤 4. 配置环境变量 -1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 +### 第 4 步:配置环境变量 - +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 -
+ - 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 +
- 2. 单击右上角的**Connect**。此时将显示连接对话框。 +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 - 3. 确保连接对话框中的配置符合你的运行环境。 +- `TIDB_HOST`:TiDB 集群的主机号。 +- `TIDB_PORT`:TiDB 集群的端口号。 +- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 +- `TIDB_DATABASE`:要连接的数据库名称。 +- `TIDB_CA_PATH`:根证书文件的路径。 - - **Endpoint Type** 设置为 `Public` - - **Branch** 设置为 `main` - - **Connect With** 设置为 `General` - - **Operating System** 与你的机器环境相匹配 +以下为 MacOS 的示例: - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 +```dotenv +TIDB_HOST=127.0.0.1 +TIDB_PORT=4000 +TIDB_USERNAME=********.root +TIDB_PASSWORD=******** +TIDB_DATABASE=test +TIDB_CA_PATH=/etc/ssl/cert.pem +``` - 4. 从连接对话框中复制连接参数。 +
- > **Tip:** - > - > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 +
- 5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 - - `TIDB_HOST`: TiDB 集群的主机号。 - - `TIDB_PORT`: TiDB 集群的端口号。 - - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - - `TIDB_DATABASE`: 要连接的数据库名称。 - - `TIDB_CA_PATH`: 根证书文件的路径。 +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 - 以下是 MacOS 的示例: +3. 确认对话框中的配置和你的运行环境一致。 - ```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 - ``` + - **Endpoint Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `General`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 -
+4. 从连接对话框中复制连接参数。 -
+ > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 - 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 - - `TIDB_HOST`: TiDB 集群的主机号。 - - `TIDB_PORT`: TiDB 集群的端口号。 - - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - - `TIDB_DATABASE`: 要连接的数据库名称。 - - `TIDB_CA_PATH`: 根证书文件的路径。 + - `TIDB_HOST`:TiDB 集群的主机号。 + - `TIDB_PORT`:TiDB 集群的端口号。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 - 以下是 MacOS 的示例: + 以下为 MacOS 的示例: ```dotenv - TIDB_HOST=127.0.0.1 + TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com TIDB_PORT=4000 TIDB_USERNAME=********.root TIDB_PASSWORD=******** @@ -138,11 +139,11 @@ pip install Django django-tidb mysqlclient numpy python-dotenv TIDB_CA_PATH=/etc/ssl/cert.pem ``` -
+
-
+ -### Step 5. 运行 demo +### Step 5. 运行示例应用程序 迁移数据库模式: @@ -156,21 +157,21 @@ python manage.py migrate python manage.py runserver ``` -打开浏览器,访问 `http://127.0.0.1:8000` 查看程序的可视化界面。以下是可用的 API 路径: +打开浏览器,访问 `http://127.0.0.1:8000` 查看该示例程序的可视化界面。以下为该程序可用的 API 路径: -| API Path | Description | +| API 路径 | 描述 | | --------------------------------------- | ---------------------------------------- | -| `POST: /insert_documents` | 插入含有向量的文件。 | -| `GET: /get_nearest_neighbors_documents` | 获取距离最近的3个文件。 | -| `GET: /get_documents_within_distance` | 获取处于给定距离内的所有文件。 | +| `POST: /insert_documents` | 插入含有向量的 `document`。 | +| `GET: /get_nearest_neighbors_documents` | 获取距离最近的 3 个 `document`。 | +| `GET: /get_documents_within_distance` | 获取处于给定距离内的所有 `document`。 | ## 示例代码片段 -你可以参考以下示例代码片段来完成自己的程序开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 ### 连接到 TiDB 集群 -在文件 `sample_project/settings.py` 中添加以下配置: +打开 `sample_project/settings.py` 文件,添加以下配置: ```python dotenv.load_dotenv() @@ -198,7 +199,7 @@ if TIDB_CA_PATH: } ``` -你可以在项目根目录下创建一个 `.env` 文件,并使用 TiDB 集群的实际值设置环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`。 +你可以在项目的根目录下创建一个 `.env` 文件,在文件中添加环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`,并根据你的TiDB 集群的实际值来设置这些变量的值。 ### 创建向量表 @@ -206,7 +207,7 @@ if TIDB_CA_PATH: `tidb-django` 提供了一个 `VectorField` ,可以在表中用来表示和存储向量类型。 -创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 ```python class Document(models.Model): @@ -214,7 +215,7 @@ class Document(models.Model): embedding = VectorField(dimensions=3) ``` -### 存储带有向量的文档 +### 存储包含向量的 `document` ```python Document.objects.create(content="dog", embedding=[1, 2, 1]) @@ -231,7 +232,7 @@ TiDB 向量支持以下距离函数: - `CosineDistance` - `NegativeInnerProduct` -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 ```python results = Document.objects.annotate( @@ -241,7 +242,7 @@ results = Document.objects.annotate( ### 搜索一定距离内的向量 -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python results = Document.objects.annotate( From 2cf3e793ddca7f99ab0ea70f03a65ab9a4371dc1 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 6 Sep 2024 14:25:50 +0800 Subject: [PATCH 019/109] Apply suggestions from code review Co-authored-by: Wenxuan --- vector-search-functions-and-operators.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index dbba4cea8a20..e002e74d2cfa 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -100,7 +100,7 @@ TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运 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),使用的公式为: +计算两个向量之间的 [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}}}$ @@ -123,7 +123,7 @@ $DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ 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) 距离,使用的公式为: +计算两个向量之间的[余弦 (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}}}}}}$ @@ -146,7 +146,7 @@ $DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \ VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2) ``` -该函数用于计算两个向量之间[内积](https://zh.wikipedia.org/wiki/%E7%82%B9%E7%A7%AF)的负值,使用的公式为: +计算两个向量之间[内积](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}}$ @@ -169,7 +169,7 @@ $DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ 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) (曼哈顿距离),使用的公式为: +计算两个向量之间的 [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}|}$ @@ -192,7 +192,7 @@ $DISTANCE(p,q)=\sum \limits _{i=1}^{n}{|p_{i}-q_{i}|}$ VEC_DIMS(vector) ``` -该函数返回给定向量的维度。 +返回向量的维度。 示例: @@ -218,7 +218,7 @@ VEC_DIMS(vector) VEC_L2_NORM(vector) ``` -该函数用于计算给定向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0)(欧几里得范数),使用的公式为: +计算向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0)(欧几里得范数),使用的公式为: $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ @@ -239,7 +239,7 @@ $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ VEC_FROM_TEXT(string) ``` -该函数用于将字符串类型转换为向量类型。 +将字符串类型转换为向量类型。 示例: @@ -258,7 +258,7 @@ VEC_FROM_TEXT(string) VEC_AS_TEXT(vector) ``` -该函数用于将向量类型转换为字符串类型。 +将向量类型转换为字符串类型。 示例: From 0eea4d71596e8429a3939b9d354f7591f9a1294e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Fri, 6 Sep 2024 14:36:26 +0800 Subject: [PATCH 020/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-changelogs.md | 15 ------- vector-search-data-types.md | 16 ++++---- vector-search-functions-and-operators.md | 52 ++++++++++++------------ vector-search-limitations.md | 2 +- vector-search-overview.md | 6 +-- 5 files changed, 38 insertions(+), 53 deletions(-) delete mode 100644 vector-search-changelogs.md diff --git a/vector-search-changelogs.md b/vector-search-changelogs.md deleted file mode 100644 index 2cb548e1910c..000000000000 --- a/vector-search-changelogs.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: 向量搜索更新日志 - -summary: 了解 TiDB 向量搜索功能的新功能、兼容性更改、改进和错误修复。 ---- - -# 向量搜索更新日志 - -## 2024 年 6 月 25 日 - -- TiDB Vector Search(测试版)现在适用于所有地区的所有用户的 TiDB Serverless 集群。 - -## 2024 年 4 月 1 日 - -- TiDB Vector Search(测试版)现适用于欧洲地区受邀用户的 TiDB Serverless 集群。 \ No newline at end of file diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 3137bcdf4bc9..eb851c3014f1 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -45,14 +45,14 @@ INSERT INTO vector_table VALUES (2, NULL); ERROR 1105 (HY000): Invalid vector text: [5, ] ``` -前面的示例中 `embedding` 向量列的维度在建表时已经定义为 `3`,因此当插入其他维度的向量数据时,TiDB 会进行报错: +下面的示例中 `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-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 ## 混合存储不同维度的向量 @@ -70,7 +70,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, ## 比较 -[比较运算符](/vector-search-functions-and-operators.md) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 +[比较运算符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符)了解向量数据类型支持的所有函数和操作符。 比较向量数据类型时,TiDB 会以向量中的各个元素为单位进行依次比较,如: @@ -148,10 +148,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 可以使用以下函数在向量和字符串之间进行转换: -- `CAST(... AS VECTOR)`: 将 String 类型转换为 Vector 类型 -- `CAST(... AS CHAR)`: 将 Vector 类型转换为 String 类型 -- `VEC_FROM_TEXT`: 将 String 类型转换为 Vector 类型 -- `VEC_AS_TEXT`: 将 Vector 类型转换为 String 类型 +- `CAST(... AS VECTOR)`: 将字符串类型转换为向量类型 +- `CAST(... AS CHAR)`: 将向量类型转换为字符串类型 +- `VEC_FROM_TEXT`: 将字符串类型转换为向量类型 +- `VEC_AS_TEXT`: 将向量类型转换为字符串类型 出于易用性考虑,如果你使用的函数只支持向量数据类型(例如,向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: @@ -229,7 +229,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 目前向量类型只支持单精度浮点数,不支持双精度浮点数。未来版本将支持这一功能。 +- 目前,向量类型不能存储双精度浮点数。计划在未来的版本中支持这一功能。在此期间,如果为向量类型导入双精度浮点数,它们将被转换为单精度数。 有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index dbba4cea8a20..0f474e6e9970 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -15,30 +15,30 @@ 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 距离 (曼哈顿距离) | +| [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_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)。 +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) | 向量类型的减法运算符 | +| [`+`](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#运算)。 @@ -47,7 +47,7 @@ TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运 | 函数名 | 描述 | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | [`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) | 返回不同数值的行数 | +| [`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) | 返回最小值 | @@ -56,21 +56,21 @@ TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运 | 名称 | 描述 | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | [`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) | 获得第一个非空参数 | +| [`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) | 空值安全相等比较符 | +| [`<=>`](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) | 检查数值是否在一组数值之内 | +| [`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) | 返回最小值 | +| [`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) | 检查数值是否不在一组数值之内 | +| [`NOT IN()`](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_not-in) | 检查值是否不在一组数值之内 | 关于如何比较向量的更多信息,请参阅[向量数据类型的比较](/vector-search-data-types.md#比较)。 @@ -87,8 +87,8 @@ TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运 | 函数名 | 描述 | | :------------------------------------------------------------------------------------------ | :----------------------------- | -| [`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()`](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)。 @@ -100,7 +100,7 @@ TiDB 扩展了以下内置函数和运算符的功能,因此这些函数和运 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),使用的公式为: +计算两个向量之间的 [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}}}$ @@ -123,7 +123,7 @@ $DISTANCE(p,q)=\sqrt {\sum \limits _{i=1}^{n}{(p_{i}-q_{i})^{2}}}$ 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) 距离,使用的公式为: +计算两个向量之间的[余弦 (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}}}}}}$ @@ -146,7 +146,7 @@ $DISTANCE(p,q)=1.0 - {\frac {\sum \limits _{i=1}^{n}{p_{i}q_{i}}}{{\sqrt {\sum \ VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2) ``` -该函数用于计算两个向量之间[内积](https://zh.wikipedia.org/wiki/%E7%82%B9%E7%A7%AF)的负值,使用的公式为: +计算两个向量之间[内积](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}}$ @@ -169,7 +169,7 @@ $DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ 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) (曼哈顿距离),使用的公式为: +计算两个向量之间的 [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}|}$ @@ -218,7 +218,7 @@ VEC_DIMS(vector) VEC_L2_NORM(vector) ``` -该函数用于计算给定向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0)(欧几里得范数),使用的公式为: +计算给定向量的 [L2 范数](https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0)(欧几里得范数),使用的公式为: $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ @@ -239,7 +239,7 @@ $NORM(p)=\sqrt {\sum \limits _{i=1}^{n}{p_{i}^{2}}}$ VEC_FROM_TEXT(string) ``` -该函数用于将字符串类型转换为向量类型。 +将字符串类型转换为向量类型。 示例: @@ -258,7 +258,7 @@ VEC_FROM_TEXT(string) VEC_AS_TEXT(vector) ``` -该函数用于将向量类型转换为字符串类型。 +将向量类型转换为字符串类型。 示例: @@ -273,7 +273,7 @@ VEC_AS_TEXT(vector) ## MySQL 兼容性 -向量数据类型只在 TiDB 中支持,MySQL 不支持。 +向量函数、有关向量的内置函数和向量数据类型运算符只在 TiDB 中支持,MySQL 不支持。 ## 另请参阅 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 549cbcc1d29e..6bded94b942d 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -9,7 +9,7 @@ summary: 本文介绍 TiDB 的向量搜索限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 目前向量类型只支持单精度浮点数,不支持双精度浮点数。未来版本将支持这一功能。 +- 目前,向量数据类型不能存储双精度浮点数。计划在未来的版本中支持这一功能。在此期间,如果为向量数据类型导入双精度浮点数,它们将被转换为单精度数。 ## 反馈 diff --git a/vector-search-overview.md b/vector-search-overview.md index ac05ac2a9eef..58415a631b6e 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -5,11 +5,11 @@ summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图 # 向量搜索概述 -TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、图像、音频和视频等多种数据类型之间进行相似度搜索。TiDB 向量搜索的 SQL 语法与 MySQL 兼容,熟悉 MySQL 的开发人员可以基于该功能轻松构建生成式人工智能 (GAI) 应用。 +TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、图像、音频和视频等多种数据类型之间进行相似度搜索。TiDB 向量搜索的 SQL 语法与 MySQL 兼容,熟悉 MySQL 的开发人员可以基于该功能轻松构建人工智能 (AI) 应用。 ## 概念 -向量搜索是一种优先考虑数据含义以提供相关结果的搜索方法。 +向量搜索是一种优先考虑数据语义以提供相关结果的搜索方法。 与传统的全文搜索(主要依赖于精确的关键词匹配和词频)不同,向量搜索通过将不同类型的数据(如文本、图像或音频)转换为高维向量,并根据这些向量之间的相似度来进行查询。这种搜索方法能够捕捉数据的语义特征和上下文信息,从而更准确地理解用户意图。 @@ -23,7 +23,7 @@ TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、 向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 -TiDB 引入了[向量数据类型](/vector-search-data-types.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以在 TiDB 中存储向量嵌入,并使用这些数据类型执行向量搜索查询,以找到最相关的数据。 +TiDB 专门引入了[向量数据类型](/vector-search-data-types.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 ### 嵌入模型 From abe5eac98657fb8e9e93307081c395ea43387f52 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 6 Sep 2024 15:22:34 +0800 Subject: [PATCH 021/109] integrate-with-peewee/sqlalchemy: refine descriptions --- vector-search-integrate-with-django-orm.md | 8 +- vector-search-integrate-with-peewee.md | 146 +++++++++++---------- vector-search-integrate-with-sqlalchemy.md | 128 +++++++++--------- 3 files changed, 142 insertions(+), 140 deletions(-) diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 278c75e89e52..14ac55152f75 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -1,11 +1,11 @@ --- -title: TiDB 向量搜索在 Django ORM 中的使用 +title: 在 Django ORM 中使用 TiDB 向量搜索 summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 --- -# TiDB 向量搜索在 Django ORM 中的使用 +# 在 Django ORM 中使用 TiDB 向量搜索 -本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 +本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 ## 前置需求 @@ -143,7 +143,7 @@ TIDB_CA_PATH=/etc/ssl/cert.pem -### Step 5. 运行示例应用程序 +### 第 5 步:运行示例应用程序 迁移数据库模式: diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index f63dbfc75eaa..ac6994eb2e24 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -1,39 +1,40 @@ --- -title: TiDB 向量搜索在 peewee 中的使用 -summary: 了解如何在 peewee 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 +title: 在 peewee 中使用 TiDB 向量搜索 +summary: 了解如何在 peewee 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 --- -# TiDB 向量搜索在 peewee 中的使用 +# 在 peewee 中使用 TiDB 向量搜索 -本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 TiDB 向量搜索进行交互、存储向量和执行向量搜索查询。 +本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 -## 准备 -在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -- TiDB Serverless 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 +## 前置需求 -- 本地部署的 TiDB 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: + +- 在你的机器上安装 [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 Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 你可以通过以下步骤快速了解如何在 peewee 中使用 TiDB 向量搜索。 -### Step 1. 克隆仓库 +### 第 1 步:克隆示例代码仓库 -将 [`tidb-vector-python`](https://github.com/pingcap/tidb-vector-python) 仓库克隆到本地计算机: +将 [`tidb-vector-python`](https://github.com/pingcap/tidb-vector-python) 仓库克隆到本地: ```shell git clone https://github.com/pingcap/tidb-vector-python.git ``` -### 步骤 2. 创建虚拟环境 +### 第 2 步:创建虚拟环境 -为项目创建虚拟环境: +为你的项目创建虚拟环境: ```bash cd tidb-vector-python/examples/orm-peewee-quickstart @@ -41,9 +42,9 @@ python3 -m venv .venv source .venv/bin/activate ``` -### 步骤 3. 安装所需的依赖项 +### 第 3 步:安装所需的依赖 -安装项目所需的依赖项: +安装项目所需的依赖: ```bash pip install -r requirements.txt @@ -55,19 +56,44 @@ pip install -r requirements.txt pip install peewee pymysql python-dotenv tidb-vector ``` -### 步骤 4. 配置环境变量 +### 第 4 步:配置环境变量 + +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 + + + +
-1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 - +- `TIDB_HOST`: TiDB 集群的主机号。 +- `TIDB_PORT`: TiDB 集群的端口号。 +- `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 +- `TIDB_DATABASE`: 要连接的数据库名称。 +- `TIDB_CA_PATH`: 根证书文件的路径。 -
+以下为 MacOS 的示例: - 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 +```dotenv +TIDB_HOST=127.0.0.1 +TIDB_PORT=4000 +TIDB_USERNAME=********.root +TIDB_PASSWORD=******** +TIDB_DATABASE=test +TIDB_CA_PATH=/etc/ssl/cert.pem +``` + +
+ +
- 2. 单击右上角的**Connect**。此时将显示连接对话框。 - 3. 确保连接对话框中的配置符合你的运行环境。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 + +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 - **Endpoint Type** 设置为 `Public` - **Branch** 设置为 `main` @@ -76,24 +102,24 @@ pip install peewee pymysql python-dotenv tidb-vector > **Tip:** > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 - 4. 从连接对话框中复制连接参数。 +4. 从连接对话框中复制连接参数。 > **Tip:** > - > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 - 5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接参数粘贴到相应的环境变量中。 - - `TIDB_HOST`: TiDB 集群的主机号。 - - `TIDB_PORT`: TiDB 集群的端口号。 - - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - - `TIDB_DATABASE`: 要连接的数据库名称。 - - `TIDB_CA_PATH`: 根证书文件的路径。 + - `TIDB_HOST`:TiDB 集群的主机号。 + - `TIDB_PORT`:TiDB 集群的端口号。 + - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 + - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 + - `TIDB_DATABASE`:要连接的数据库名称。 + - `TIDB_CA_PATH`:根证书文件的路径。 - 以下是 MacOS 的示例: + 以下为 MacOS 的示例: ```dotenv TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com @@ -104,41 +130,17 @@ pip install peewee pymysql python-dotenv tidb-vector TIDB_CA_PATH=/etc/ssl/cert.pem ``` -
- -
- - 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 - - - `TIDB_HOST`: TiDB 集群的主机号。 - - `TIDB_PORT`: TiDB 集群的端口号。 - - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - - `TIDB_DATABASE`: 要连接的数据库名称。 - - `TIDB_CA_PATH`: 根证书文件的路径。 - - 以下是 MacOS 的示例: - - ```dotenv - TIDB_HOST=127.0.0.1 - TIDB_PORT=4000 - TIDB_USERNAME=********.root - TIDB_PASSWORD=******** - TIDB_DATABASE=test - TIDB_CA_PATH=/etc/ssl/cert.pem - ``` - -
+
-
+ -### 步骤 5. 运行 demo +### 第 5 步:运行示例应用程序 ```bash python peewee-quickstart.py ``` -输出示例 +输出示例: ```text Get 3-nearest neighbor documents: @@ -157,11 +159,11 @@ Get documents within a certain distance: ## 示例代码片段 -你可以参考以下示例代码片段来完成自己的程序开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 ### 创建向量表 -#### 连接至 TiDB 集群 +#### 连接到 TiDB 集群 ```python import os @@ -200,7 +202,7 @@ db = MySQLDatabase( #### 定义向量列 -创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 ```python class Document(Model): @@ -212,7 +214,7 @@ class Document(Model): embedding = VectorField(3) ``` -### 存储带有向量的文档 +### 存储包含向量的 `document` ```python Document.create(content='dog', embedding=[1, 2, 1]) @@ -222,7 +224,7 @@ Document.create(content='tree', embedding=[1, 0, 0]) ### 搜索近邻向量 -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 ```python distance = Document.embedding.cosine_distance([1, 2, 3]).alias('distance') @@ -231,7 +233,7 @@ results = Document.select(Document, distance).order_by(distance).limit(3) ### 搜索一定距离内的向量 -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python distance_expression = Document.embedding.cosine_distance([1, 2, 3]) diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 1a25d3a2d7df..b299c55ba3b2 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -1,30 +1,30 @@ --- -title: TiDB 向量搜索在 SQLAlchemy 中的使用 -summary: 了解如何在 SQLAlchemy 中 TiDB 使用向量搜索,,以存储向量并执行语义搜索。 +title: 在 SQLAlchemy 中使用 TiDB 向量搜索 +summary: 了解如何在 SQLAlchemy 中通过 TiDB 向量搜索功能存储向量并执行语义搜索。 --- -# TiDB 向量搜索在 SQLAlchemy 中的使用 +# 在 SQLAlchemy 中使用 TiDB 向量搜索 -本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互、存储向量和执行向量搜索查询。 +本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 +## 前置需求 -## 准备 -在开始之前,你需要确定 TiDB 集群的部署方式以及以下内容被正确安装, -- TiDB Serverless 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB Serverless集群。如果没有 TiDB Cloud 集群,请按照[创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html)创建自己的 TiDB Cloud 集群。 +为了能够顺利完成本文中的操作,你需要提前: -- 本地部署的 TiDB 集群 - - [Python 3.8 or higher](https://www.python.org/downloads/) - - [Git](https://git-scm.com/downloads) - - TiDB 集群。如果没有集群,请按照[使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md)创建自己的 TiDB 集群。 +- 在你的机器上安装 [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 Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 你可以通过以下步骤快速了解如何在 SQLAlchemy 中使用 TiDB 向量搜索。 -### 步骤 1. 克隆仓库 +### 第 1 步:克隆示例代码仓库 将 `tidb-vector-python` 仓库克隆到本地: @@ -32,9 +32,9 @@ summary: 了解如何在 SQLAlchemy 中 TiDB 使用向量搜索,,以存储 git clone https://github.com/pingcap/tidb-vector-python.git ``` -### 步骤 2. 创建虚拟环境 +### 第 2 步:创建虚拟环境 -为项目创建虚拟环境: +为你的项目创建虚拟环境: ```bash cd tidb-vector-python/examples/orm-sqlalchemy-quickstart @@ -42,9 +42,9 @@ python3 -m venv .venv source .venv/bin/activate ``` -### 步骤 3. 安装所需的依赖项 +### 第 3 步:安装所需的依赖 -安装示例项目所需的依赖项: +安装示例项目所需的依赖: ```bash pip install -r requirements.txt @@ -56,72 +56,72 @@ pip install -r requirements.txt pip install pymysql python-dotenv sqlalchemy tidb-vector ``` -### 步骤 4. 配置环境变量 -1. 根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 +### 第 4 步:配置环境变量 - +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 -
+ - 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 页面,单击目标群集的名称进入其概览页面。 +
- 2. 单击右上角的**Connect**。此时将显示连接对话框。 +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 - 3. 确保连接对话框中的配置符合你的运行环境。 +- `HOST`:TiDB 集群的主机。 +- `PORT`:TiDB 集群的端口。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。 +- `CA`:根证书文件的路径。 - - **Endpoint Type** 设置为 `Public` - - **Branch** 设置为 `main` - - **Connect With** 设置为 `General` - - **Operating System** 与你的机器环境相匹配 +以下为 MacOS 的示例: - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://.root:@127.0.0.1:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` - 4. 单击 **PyMySQL** 标签,复制连接字符串。 +
- > **Tip:** - > - > 如果尚未设置密码,单击**生成密码**生成一个随机密码。 +
- 5. 在 Python 项目的根目录下创建一个 `.env` 文件,并将连接字符串粘贴到其中。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 - 以下是 MacOS 的示例: +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 - ```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" - ``` +3. 确认对话框中的配置和你的运行环境一致。 + + - **Endpoint Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `General`。 + - **Operating System** 为你的运行环境。 -
+ > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 -
+4. 单击 **PyMySQL** 选项卡,复制连接字符串。 - 在 Python 项目的根目录下创建一个 `.env` 文件,并根据启动的集群参数修改相应的环境变量中。 + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 - - `HOST`: TiDB 集群的主机。 - - `PORT`: TiDB 集群的端口。 - - `USERNAME`: 连接 TiDB 集群的用户名。 - - `PASSWORD`: 连接 TiDB 集群的密码。 - - `DATABASE`: 要连接的数据库名称。 - - `CA`: 根证书文件的路径。 +5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接字符串粘贴到其中。 - 以下是 MacOS 的示例: + 以下为 MacOS 的示例: ```dotenv - TIDB_DATABASE_URL="mysql+pymysql://.root:@127.0.0.1:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" + 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. 运行demo +### 第 5 步:运行示例应用程序 ```bash python sqlalchemy-quickstart.py ``` -输出示例: +输出示例: ```text Get 3-nearest neighbor documents: @@ -140,11 +140,11 @@ Get documents within a certain distance: ## 示例代码片段 -你可以参考以下示例代码片段来完成自己的程序开发。 +你可以参考以下示例代码片段来完成自己的应用程序开发。 ### 创建向量表 -#### 连接至 TiDB 集群 +#### 连接到 TiDB 集群 ```python import os @@ -162,7 +162,7 @@ engine = create_engine(tidb_connection_string) #### 定义向量列 -创建一个表格,其中有一列向量类型的 `embedding` ,用于存储三维向量。 +创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 ```python Base = declarative_base() @@ -174,7 +174,7 @@ class Document(Base): embedding = Column(VectorType(3)) ``` -### 存储带有向量的文档 +### 存储包含向量的 `document` ```python with Session(engine) as session: @@ -186,7 +186,7 @@ with Session(engine) as session: ### 搜索近邻向量 -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个内容。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 ```python with Session(engine) as session: @@ -198,7 +198,7 @@ with Session(engine) as session: ### 搜索一定距离内的向量 -我们可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 +可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 的余弦距离小于 0.2 的向量。 ```python with Session(engine) as session: From 48f47afedfdee9d0adeb8e96bd74b04839285e50 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 6 Sep 2024 17:21:57 +0800 Subject: [PATCH 022/109] get-started and integrate-with-jinaai-embedding: refine descriptions --- vector-search-get-started-using-python.md | 39 ++--- vector-search-get-started-using-sql.md | 51 ++++++- ...-search-integrate-with-jinaai-embedding.md | 141 +++++++++--------- 3 files changed, 137 insertions(+), 94 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index f031d9480981..1c82f0c06b2e 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -19,8 +19,8 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -53,6 +53,25 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv +
+ +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 + +- `HOST`:TiDB 集群的主机号。 +- `PORT`:TiDB 集群的端口。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。 +- `CA_PATH`:根证书文件的路径。 + +以下为 MacOS 的示例: + +```dotenv +TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` + +
+
1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 @@ -86,24 +105,6 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv
-
- -在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 - -- `HOST`:TiDB 集群的主机号。 -- `PORT`:TiDB 集群的端口。 -- `USERNAME`:连接 TiDB 集群的用户名。 -- `PASSWORD`:连接 TiDB 集群的密码。 -- `DATABASE`:要连接的数据库名称。 -- `CA_PATH`:根证书文件的路径。 - -以下为 MacOS 的示例: - -```dotenv -TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" -``` - -
### 第 4 步:初始化嵌入模型 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index d14a9b5a21d4..4a2b54f713c3 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -23,8 +23,8 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -32,19 +32,56 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 根据不同的 TiDB 部署方式,使用不同的方法连接到 TiDB 集群。 -将连接命令输入至终端。以下是 macOS 的示例: + + +
+ +在本地部署的集群启动后,将你的集群连接命令输入至终端: + +以下为 MacOS 的示例: + +```bash + mysql --comments --host 127.0.0.1 --port 4000 -u root +``` + +
+ +
+ +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 -- TiDB Serverless 集群 +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 + +3. 确认对话框中的配置和你的运行环境一致。 + + - **Endpoint Type** 为 `Public`。 + - **Branch** 选择 `main`。 + - **Connect With** 选择 `MySQL CLI`。 + - **Operating System** 为你的运行环境。 + + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 + +4. 点击 **Connection String**,然后复制连接字符串。 + + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 + +5. 在终端中执行连接字符串命令: + + 以下为 macOS 上的连接字符串示例: ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' ``` -- 本地部署的 TiDB 集群 + 注意替换 `<>` 中的占位符为你的集群实际对应的值。 - ```bash - mysql --comments --host 127.0.0.1 --port 4000 -u root - ``` +
+ +
### 第 2 步:创建向量表 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 1f1c97fb9529..3d426144837b 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -9,17 +9,22 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, ## 前置需求 -- 推荐 [Python 3.8](https://www.python.org/downloads/) 及以上版本。 -- [Git](https://git-scm.com/downloads)。 -- TiDB 集群,如果你还没有 TiDB 集群,可以按照以下方式创建: - - TiDB Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 - - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: -## 运行示例程序 +- 在你的机器上安装 [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 Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 + +## 运行示例应用程序 您可以通过以下步骤快速了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索。 -### 步骤 1. 克隆代码库 +### 第 1 步:克隆示例代码仓库 将 `tidb-vector-python` 仓库克隆到本地: @@ -27,9 +32,9 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, git clone https://github.com/pingcap/tidb-vector-python.git ``` -### 步骤 2. 创建虚拟环境 +### 第 2 步:创建虚拟环境 -为项目创建虚拟环境: +为你的项目创建虚拟环境: ```bash cd tidb-vector-python/examples/jina-ai-embeddings-demo @@ -37,95 +42,95 @@ python3 -m venv .venv source .venv/bin/activate ``` -### 步骤 3. 安装所需的依赖项 +### 第 3 步:安装所需的依赖 -安装项目所需的依赖项: +安装项目所需的依赖: ```bash pip install -r requirements.txt ``` -### 步骤 4. 配置环境变量 +### 第 4 步:配置环境变量 #### 4.1 获取 Jina AI API 密钥 从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥。 - +#### 4.2 配置 TiDB 连接参数 -
- -#### 4.2 获取 TiDB 连接参数 - -1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 + -2. 单击右上角的**Connect**。此时将显示连接对话框。 +
-3. 确保连接对话框中的配置符合您的运行环境。 +1. 在项目的根目录下新建一个 `.env` 文件: - - **Connection Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `SQLAlchemy`. - - **Operating System** 与你的系统环境相匹配. + ```dotenv + - TIDB_HOST='{host}' + - TIDB_PORT='4000' + - TIDB_USER='root' + - TIDB_PASSWORD='{password}' + - TIDB_DB_NAME='test' + ``` - > **Tip:** - > - > 如果程序在 Windows Subsystem for Linux (WSL) 中运行,请切换到相应的 Linux 发行版。 + 注意替换 `{}` 中的占位符为你的 TiDB 实际对应的值,并删除 CA_PATH 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 +2. 在终端中设置环境变量: -4. 点击 **PyMySQL** 标签,复制连接字符串。 + ```dotenv + JINAAI_API_KEY="****" + TIDB_DATABASE_URL="{tidb_connection_string}" + ``` - > **Tip:** - > - > 如果尚未设置密码,请单击**Generate Password**生成一个随机密码。 + 以下为 MacOS 的示例: -#### 4.3 设置环境变量 + ```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" + ``` -在终端中设置环境变量,或创建一个包含上述环境变量的 `.env` 文件。 + 注意替换其中的占位符为你的 TiDB 实际对应的值。 +
-```dotenv -JINAAI_API_KEY="****" -TIDB_DATABASE_URL="{tidb_connection_string}" -``` +
-例如,macOS 上的连接字符串如下所示: +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 -```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" -``` +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 -
+3. 确认对话框中的配置和你的运行环境一致。 -
+ - **Connection Type** 为 `Public`. + - **Branch** 选择 `main`. + - **Connect With** 选择 `SQLAlchemy`. + - **Operating System** 为你的运行环境。 -#### 4.2 设置 TiDB 连接参数 + > **Tip:** + > + > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 -- 创建一个包含如下环境变量的 `.env` 文件: - - TIDB_HOST='{host}' - - TIDB_PORT='4000' - - TIDB_USER='root' - - TIDB_PASSWORD='{password}' - - TIDB_DB_NAME='test' +4. 点击 **PyMySQL** 选项卡,复制连接字符串。 - 注意替换 {} 中的占位符为你的 TiDB 对应的值,并删除 CA_PATH 这行。如果你在本机运行 TiDB,默认 Host 地址为 127.0.0.1,密码为空。 + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 -- 在终端中设置环境变量 +5. 在终端中将 Jina AI API 密钥以及连接字符串设置为环境变量,或创建一个包含以下环境变量的 `.env` 文件。 ```dotenv JINAAI_API_KEY="****" TIDB_DATABASE_URL="{tidb_connection_string}" ``` - 例如,macOS 上的连接字符串如下所示: + + 以下为 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" ``` - 注意替换为你的 TiDB 实际对应的值。 -
+
-### 步骤 5. 运行示例 +### 第 5 步:运行示例应用程序 ```bash python jina-ai-embeddings-demo.py @@ -149,7 +154,7 @@ python jina-ai-embeddings-demo.py ## 示例代码片段 -### 从 Jina AI 获取嵌入信息 +### 通过 Jina AI 获取嵌入信息 定义一个 `generate_embeddings` 函数,用于调用 Jina AI 的嵌入 API: @@ -176,9 +181,9 @@ def generate_embeddings(text: str): return response.json()['data'][0]['embedding'] ``` -### 连接至 TiDB Serverless +### 连接到 TiDB 集群 -通过 SQLAlchemy 连接 TiDB Serverless: +通过 SQLAlchemy 连接 TiDB 集群: ```python import os @@ -194,9 +199,9 @@ assert TIDB_DATABASE_URL is not None engine = create_engine(url=TIDB_DATABASE_URL, pool_recycle=300) ``` -### 定义向量表模式 +### 定义向量表结构 -创建名为 `jinaai_tidb_demo_documents` 的表,其中的 `content` 列用于存储文本,名为 `content_vec` 的向量列用于存储向量嵌入: +创建一张 `jinaai_tidb_demo_documents` 表,其中包含一个 `content` 列用于存储文本,一个 `content_vec` 向量列用于存储向量嵌入: ```python from sqlalchemy import Column, Integer, String, create_engine @@ -218,12 +223,12 @@ class Document(Base): > **Note:** > -> - 向量列的维度必须与嵌入模型生成的向量嵌入维度相匹配。 -> - 在本例中,`jina-embeddings-v2-base-en` 模型生成的向量嵌入维度是 “768”。 +> - 向量列的维度必须与嵌入模型生成的向量嵌入维度相同。 +> - 在本例中,`jina-embeddings-v2-base-en` 模型生成的向量嵌入维度为 `768`。 -### 使用 Jina AI 生成向量嵌入并存入 TiDB +### 使用 Jina AI 生成向量嵌入并存入 TiDB -使用 Jina AI 嵌入 API 为每个文本生成向量嵌入,并将这些向量存储在 TiDB 中: +使用 Jina AI 嵌入 API 为每条文本生成向量嵌入,并将这些向量存储在 TiDB 中: ```python TEXTS = [ @@ -233,7 +238,7 @@ TEXTS = [ data = [] for text in TEXTS: - # Generate embeddings for the texts via Jina AI API. + # 通过 Jina AI API 生成文本的向量嵌入 embedding = generate_embeddings(text) data.append({ 'text': text, @@ -253,11 +258,11 @@ with Session(engine) as session: ### 使用 Jina AI 生成的向量嵌入在 TiDB 中执行语义搜索 -通过 Jina AI 嵌入 API 生成查询文本的向量嵌入,然后根据查询向量嵌入和文档向量嵌入之间的余弦距离搜索最相关的文档: +通过 Jina AI 的嵌入 API 生成查询文本的向量嵌入,然后根据**查询文本的向量嵌入**和**向量表中各个向量嵌入**之间的余弦距离搜索最相关的 `document`: ```python query = 'What is TiDB?' -# 通过 Jina AI API 生成查询向量嵌入 +# 通过 Jina AI API 生成查询文本的向量嵌入 query_embedding = generate_embeddings(query) with Session(engine) as session: From f9b6dc0c5bcdc55f1b31ba622ff3c30093362977 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 6 Sep 2024 17:36:30 +0800 Subject: [PATCH 023/109] get-started-using-sql: update connection instructions --- vector-search-get-started-using-sql.md | 31 ++++++-------------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index 4a2b54f713c3..7a684d50e168 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -36,9 +36,9 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md)
-在本地部署的集群启动后,将你的集群连接命令输入至终端: +在本地部署的集群启动后,在终端中执行你的集群连接命令: -以下为 MacOS 的示例: +以下为 MacOS 上的连接命令示例: ```bash mysql --comments --host 127.0.0.1 --port 4000 -u root @@ -52,33 +52,16 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 -3. 确认对话框中的配置和你的运行环境一致。 +3. 在连接对话框中,选择 **Connect With** 下拉列表中的 **MySQL CLI**,并保留 **Endpoint Type** 的默认值为 **Public**。 - - **Endpoint Type** 为 `Public`。 - - **Branch** 选择 `main`。 - - **Connect With** 选择 `MySQL CLI`。 - - **Operating System** 为你的运行环境。 +4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 - > **Tip:** - > - > 如果你的程序在 Windows Subsystem for Linux (WSL) 中运行,请切换为对应的 Linux 发行版。 - -4. 点击 **Connection String**,然后复制连接字符串。 - - > **Tip:** - > - > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 - -5. 在终端中执行连接字符串命令: - - 以下为 macOS 上的连接字符串示例: +5. 复制对话框中的连接命令,并粘贴到终端中执行。以下为 macOS 上的连接命令示例: ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' ``` - 注意替换 `<>` 中的占位符为你的集群实际对应的值。 -
@@ -156,7 +139,7 @@ SELECT * FROM embedded_documents; 与全文搜索类似,在使用向量搜索时,你需要指定搜索词。 -在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用嵌入模型将用户的搜索词转换为向量。 +在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用[嵌入模型](/vector-search-overview.md#嵌入模型)将用户的搜索词转换为向量。 执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量 (余弦距离最小) 的前三个向量。 @@ -180,7 +163,7 @@ LIMIT 3; 3 rows in set (0.15 sec) ``` -搜索结果中的 3 个词会按向量的远近排列:距离越小,对应的 `document` 越相关。 +搜索结果中的 3 个词会按向量的距离排列:距离越小,对应的 `document` 越相关。 因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 From ae9486479bbdcdc23163295d3f6b05ac2155ddf3 Mon Sep 17 00:00:00 2001 From: Wenxuan Date: Fri, 6 Sep 2024 22:20:57 +0800 Subject: [PATCH 024/109] Update vector-search-data-types.md Co-authored-by: JaySon --- vector-search-data-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index eb851c3014f1..f5e0981b765b 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -130,7 +130,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, +---------------------------------------------+ 1 row in set (0.01 sec) -mysql> SELECT VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]'); +[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]') | +-----------------------------------------------------+ From f485b583ebb5290382b7587a41a964916ad5a6e7 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 9 Sep 2024 12:01:18 +0800 Subject: [PATCH 025/109] integrate-with-llamaindex: refine descriptions --- vector-search-integrate-with-llamaindex.md | 160 ++++++++++----------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 9865f198c1f3..d7820e39caa7 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -1,40 +1,45 @@ --- title: 在 LlamaIndex 中使用 TiDB 向量搜索 -summary: 展示如何在 LlamaIndex 中使用 TiDB 向量搜索 +summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 --- # 在 LlamaIndex 中使用 TiDB 向量搜索 -本文档展示如何在 [LlamaIndex](https://www.llamaindex.ai) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 +本文档将展示如何在 [LlamaIndex](https://www.llamaindex.ai) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 > **Note** > -> - 您可以在 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) 在线环境中运行示例代码。 +> 你可以在 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 Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 - - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: -## 开始 +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Jupyter Notebook](https://jupyter.org/install) +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 -本节将逐步说明如何在 LlamaIndex 中使用 TiDB 向量搜索进行语义搜索。 +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: -### 步骤 1. 创建新的 Jupyter Notebook 文件 +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 -在根目录下新建一个名为 `integrate_with_llamaindex.ipynb` 的 Jupyter Notebook 文件: +## 快速开始 + +本节将详细介绍如何将 TiDB 的向量搜索功能与 LlamaIndex 结合使用,以实现语义搜索。 + +### 第 1 步:新建 Jupyter Notebook 文件 + +在根目录下,新建一个名为 `integrate_with_llamaindex.ipynb` 的 Jupyter Notebook 文件: ```shell touch integrate_with_llamaindex.ipynb ``` -### 步骤 2. 安装所需依赖 +### 第 2 步:安装所需的依赖 -在项目目录下运行以下命令安装所需的软件包: +在你的项目目录下,运行以下命令安装所需的软件包: ```shell pip install llama-index-vector-stores-tidbvector @@ -51,36 +56,13 @@ from llama_index.core import VectorStoreIndex from llama_index.vector_stores.tidbvector import TiDBVectorStore ``` -### 步骤 3. 设置环境 +### 第 3 步:配置环境变量 -
- -#### 步骤 3.1 获取 TiDB 群集的连接字符串 - - 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 - - 2. 单击右上角的**Connect**。此时将显示连接对话框。 - - 3. 确保连接对话框中的配置符合您的运行环境。 - - - **Connection Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `SQLAlchemy`. - - **Operating System** 与你的系统环境相匹配. - - 4. 点击 **PyMySQL** 标签,复制连接字符串。 - - > **Tip:** - > - > 如果尚未设置密码,请单击**Generate Password**生成一个随机密码。 - -#### 步骤 3.2 配置环境变量 - -要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 +
-本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: @@ -95,54 +77,72 @@ 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://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` + +注意替换为你的 TiDB 实际对应的值。 +
-
+
-#### 步骤 3.1 配置环境变量 +对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 群集的连接字符串,然后配置环境变量: -要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 -本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 -运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: +3. 确认对话框中的配置和你的运行环境一致。 -```python -# Use getpass to securely prompt for environment variables in your terminal. -import getpass -import os + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`. + - **Connect With** 选择 `SQLAlchemy`. + - **Operating System** 为你的运行环境。 -# 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. 点击 **PyMySQL** 选项卡,复制连接字符串。 -例如,macOS 上的连接字符串如下所示: + > **Tip:** + > + > 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 -```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" -``` -注意替换为你的 TiDB 实际对应的值。 +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 步:加载样本文档 -#### 步骤 4.1 下载样本文件 +#### 4.1 下载样本文档 -在项目目录中创建名为 `data/paul_graham/` 的目录,并从 [run-llama/llama_index](https://github.com/run-llama/llama_index) 代码库中下载示例文档 [`paul_graham_essay.txt`](https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt)。 +在你的项目目录中创建一个名为 `data/paul_graham/` 的目录,然后从 [run-llama/llama_index](https://github.com/run-llama/llama_index) 代码库中下载样本文档 [`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 加载文件 +#### 4.2 加载文档 -使用 `SimpleDirectoryReader` 从 `data/paul_graham/paul_graham_essay.txt` 中加载示例文档。 +使用 `SimpleDirectoryReader` 从 `data/paul_graham/paul_graham_essay.txt` 中加载示例文档: ```python documents = SimpleDirectoryReader("./data/paul_graham").load_data() @@ -152,11 +152,11 @@ for index, document in enumerate(documents): document.metadata = {"book": "paul_graham"} ``` -### 步骤 5. 向量的生成和存储 +### 第 5 步:生成并存储文档向量 -#### 步骤 5.1 初始化 TiDB 向量存储 +#### 5.1 初始化 TiDB 向量存储 -以下代码在 TiDB 中创建了一个名为 `paul_graham_test` 的表,该表针对向量搜索进行了优化。 +以下代码将在 TiDB 中创建一个 `paul_graham_test` 表,该表针对向量搜索进行了优化。 ```python tidbvec = TiDBVectorStore( @@ -170,9 +170,9 @@ tidbvec = TiDBVectorStore( 执行成功后,你可以直接查看和访问 TiDB 数据库中的 `paul_graham_test` 表。 -#### 步骤 5.2 生成并存储向量 +#### 5.2 生成并存储向量嵌入 -下面的代码会解析文档、生成向量嵌入并将其存储到 TiDB 向量存储中。 +以下代码将解析文档以生成向量嵌入,并将向量嵌入存储到 TiDB 向量存储中。 ```python storage_context = StorageContext.from_defaults(vector_store=tidbvec) @@ -188,9 +188,9 @@ 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. 执行向量搜索 +### 第 6 步:执行向量搜索 -下面将基于 TiDB 向量存储创建一个查询引擎,并执行语义相似性搜索。 +以下代码将基于 TiDB 向量存储创建一个查询引擎,并执行语义相似性搜索。 ```python query_engine = index.as_query_engine() @@ -210,13 +210,13 @@ publishing essays online, developing spam filters, painting, hosting dinner part a building for office use. ``` -### 步骤 7. 使用元数据过滤器搜索 +### 第 7 步:使用元数据过滤器进行搜索 -为了优化搜索,你可以使用元数据筛选器来获取符合所设置筛选条件的特定近邻结果。 +为了优化搜索,你可以使用元数据过滤器来筛选出符合特定条件的近邻结果。 #### 使用 `book != “paul_graham”` 过滤器查询 -以下示例查询了去除 `book` 元数据字段为 `paul_graham` 后的结果: +以下示例的查询将排除掉 `book` 元数据字段为 `paul_graham` 的结果: ```python from llama_index.core.vector_stores.types import ( @@ -236,7 +236,7 @@ response = query_engine.query("What did the author learn?") print(textwrap.fill(str(response), 100)) ``` -预期输出如下 +预期输出如下: ```plain Empty Response @@ -244,7 +244,7 @@ Empty Response #### Query with `book == "paul_graham"` filter -以下示例查询了 `book` 元数据字段为 `paul_graham` 的结果: +以下示例的查询将筛选出 `book` 元数据字段为 `paul_graham` 的结果: ```python from llama_index.core.vector_stores.types import ( @@ -274,15 +274,15 @@ Later on, the author attended art school in both the US and Italy, where they ob substantial teaching in the painting department. ``` -### 步骤 8. 删除文件 +### 第 8 步:删除文档 -从索引中删除第一个文件: +从索引中删除第一个文档: ```python tidbvec.delete(documents[0].doc_id) ``` -检查文件是否已被删除: +检查文档是否已被删除: ```python query_engine = index.as_query_engine() From 2e56e202be9db1cd3e97cecacf25c6631e1feb71 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 9 Sep 2024 15:27:39 +0800 Subject: [PATCH 026/109] integrate-with-langchain: refine descriptions --- vector-search-integrate-with-langchain.md | 209 +++++++++++----------- 1 file changed, 104 insertions(+), 105 deletions(-) diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index e686506d844c..f478a4e95472 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -5,36 +5,41 @@ summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 # 在 LangChain 中使用 TiDB 向量搜索 -本文档展示如何在 [LangChain](https://python.langchain.com/) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 +本文档将展示如何在 [LangChain](https://python.langchain.com/) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 > **Note** > -> - 您可以在 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) 在线环境中运行示例代码。 +> 你可以在 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 Serverless 集群。如果没有 TiDB Cloud 集群,请按照 [创建 TiDB Serverless集群](https://dev.mysql.com/doc/refman/8.4/en/mysql.html) 创建自己的 TiDB Cloud 集群。 - - 本地部署的 TiDB 集群。如果没有集群,请按照 [使用 TiUP 部署 TiDB 集群](/production-deployment-using-tiup.md) 创建自己的 TiDB 集群。 +为了能够顺利完成本文中的操作,你需要提前: -## 开始 +- 在你的机器上安装 [Python 3.8](https://www.python.org/downloads/) 或更高版本 +- 在你的机器上安装 [Jupyter Notebook](https://jupyter.org/install) +- 在你的机器上安装 [Git](https://git-scm.com/downloads) +- 准备一个 TiDB 集群 -本节将逐步说明如何在 LangChain 中使用 TiDB 向量搜索进行语义搜索。 +如果你还没有 TiDB 集群,可以按照以下任一种方式创建: -### 步骤 1. 创建新的 Jupyter Notebook 文件 +- 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 +- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 -在根目录下新建一个名为 `integrate_with_langchain.ipynb` 的 Jupyter Notebook 文件: +## 快速开始 + +本节将详细介绍如何将 TiDB 的向量搜索功能与 LangChain 结合使用,以实现语义搜索。 + +### 第 1 步:新建 Jupyter Notebook 文件 + +在根目录下,新建一个名为 `integrate_with_langchain.ipynb` 的 Jupyter Notebook 文件: ```shell touch integrate_with_langchain.ipynb ``` -### 步骤 2. 安装所需的依赖项 +### 第 2 步:安装所需的依赖 -在项目目录下运行以下命令安装所需的软件包: +在你的项目目录下,运行以下命令安装所需的软件包: ```shell !pip install langchain langchain-community @@ -52,35 +57,13 @@ from langchain_openai import OpenAIEmbeddings from langchain_text_splitters import CharacterTextSplitter ``` -### 步骤 3. 设置环境 - - -
- -#### 步骤 3.1 获取 TiDB 群集的连接字符串 - - 1. 在 [**Cluster**](https://tidbcloud.com/console/clusters) 界面,单击目标群集的名称进入其概览页面。 - - 2. 单击右上角的**Connect**。此时将显示连接对话框。 - - 3. 确保连接对话框中的配置符合您的运行环境。 - - - **Connection Type** 设置为 `Public`. - - **Branch** 设置为 `main`. - - **Connect With** 设置为 `SQLAlchemy`. - - **Operating System** 与你的系统环境相匹配. - - 4. 点击 **PyMySQL** 标签,复制连接字符串。 - - > **Tip:** - > - > 如果尚未设置密码,请单击**Generate Password**生成一个随机密码。 +### 第 3 步:配置环境变量 -#### 步骤 3.2 配置环境变量 + -要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 +
-本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: @@ -95,51 +78,70 @@ 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://.root:@gateway01..prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +``` + +注意替换为你的 TiDB 实际对应的值。 +
-
+
-#### 步骤 3.1 配置环境变量 +对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 群集的连接字符串,然后配置环境变量: -要建立安全高效的数据库连接,请使用 TiDB 提供的标准连接方法。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 -本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从步骤 3.1 中获取的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 +2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 -运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: +3. 确认对话框中的配置和你的运行环境一致。 -```python -# Use getpass to securely prompt for environment variables in your terminal. -import getpass -import os + - **Connection Type** 为 `Public`。 + - **Branch** 选择 `main`. + - **Connect With** 选择 `SQLAlchemy`. + - **Operating System** 为你的运行环境。 -# 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 上的连接字符串如下所示: +4. 点击 **PyMySQL** 选项卡,复制连接字符串。 -```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" -``` -注意替换为你的 TiDB 实际对应的值。 + > **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 步:加载样本文档 -#### 步骤 4.1 下载样本文件 +#### 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) 。 +在你的项目目录中创建一个名为 `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 加载和分割文件 +#### 4.2 加载并分割文档 从 `data/how_to/state_of_the_union.txt` 中加载示例文档,并使用 `CharacterTextSplitter` 将其分割成每块约 1000 个字符的文本块。 @@ -150,11 +152,11 @@ text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) docs = text_splitter.split_documents(documents) ``` -### 步骤 5. 向量的生成和存储 +### 第 5 步:生成并存储文档向量 TiDB 支持使用余弦距离 (`cosine`) 和欧式距离 (`L2`) 来评估向量之间的相似性。在存储向量时,默认使用余弦距离。 -以下代码在 TiDB 中创建了表 `embedded_documents`,该表针针对向量搜索进行了优化。 +以下代码将在 TiDB 中创建一个 `embedded_documents` 表,该表针对向量搜索进行了优化。 ```python embeddings = OpenAIEmbeddings() @@ -169,17 +171,17 @@ vector_store = TiDBVectorStore.from_documents( 成功执行后,你可以直接查看和访问 TiDB 数据库中的 `embedded_documents` 表。 -### 步骤 6. 执行向量搜索 +### 第 6 步:执行向量搜索 -本节展示如何在文档 `state_of_the_union.txt` 中查询 "What did the president say about Ketanji Brown Jackson"。 +本节将展示如何在 `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" ``` -#### 选项 1:使用 `similarity_search_with_score()` +#### 方式一:使用 `similarity_search_with_score()` -`similarity_search_with_score()` 方法计算文档内容与查询语句之间的向量距离。该距离可作为相似性得分,距离的计算方式可由所选的 `distance_strategy` 决定。该方法会返回得分最低的前 `k` 个文档。得分越低,说明文档与查询之间的相似度越高。 +`similarity_search_with_score()` 方法用于计算文档内容与查询语句之间的向量距离。该距离是一个相似度的得分,其计算方式由所选的 `distance_strategy` 决定。该方法会返回得分最低的前 `k` 个文档。得分越低,说明文档与你的查询语句之间的相似度越高。 ```python docs_with_score = vector_store.similarity_search_with_score(query, k=3) @@ -191,7 +193,7 @@ for doc, score in docs_with_score: ```
- Expected output + 预期输出 ```plain -------------------------------------------------------------------------------- @@ -236,7 +238,7 @@ First, beat the opioid epidemic.
-#### 选项 2:使用 `similarity_search_with_relevance_scores()` 方法 +#### 方式二:使用 `similarity_search_with_relevance_scores()` 方法 `similarity_search_with_relevance_scores()` 方法会返回相关性得分最高的前`k`个文档。分数越高,说明文档内容与你的查询语句之间的相似度越高。 @@ -250,7 +252,7 @@ for doc, score in docs_with_relevance_score: ```
- Expected output + 预期输出 ```plain -------------------------------------------------------------------------------- @@ -283,8 +285,7 @@ We’re securing commitments and supporting partners in South and Central Americ ### 检索器 -在 Langchain 中,[检索器](https://python.langchain.com/v0.2/docs/concepts/#retrievers) 是一种接口,用于响应非结构化查询检索,并提供比向量存储更多的功能。以下代码演示了如何将 TiDB 向量存储用作检索器。 - +在 Langchain 中,[检索器](https://python.langchain.com/v0.2/docs/concepts/#retrievers)是一个接口,用于响应非结构化查询,检索相关文档。相比于向量存储,检索器可以为你提供更多的功能。以下代码演示了如何将 TiDB 向量存储用作检索器。 ```python retriever = vector_store.as_retriever( @@ -320,19 +321,17 @@ And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketan vector_store.drop_vectorstore() ``` -## 使用元数据过滤器搜索 - -To refine your searches, you can use metadata filters to retrieve specific nearest-neighbor results that match the applied filters. +## 使用元数据过滤器进行搜索 -你可以使用元数据过滤器来检索与所应用的过滤器相匹配的特定近邻结果,以进一步改进搜索。 +为了优化搜索,你可以使用元数据过滤器来筛选出符合特定条件的近邻结果。 ### 支持的元数据类型 -TiDB 向量存储中的每个文档都可以与元数据配对,元数据的结构是 JSON 对象中的键值对。键的类型一般是字符串,而值可以是以下任何类型: +在 TiDB 向量存储中,每个文档都可以与元数据配对。元数据的结构是 JSON 对象中的键值对 (key-value pairs) 形式。键 (key) 的类型是字符串,而值 (value) 可以是以下任何类型: - 字符串 -- 数值: integer 或 floating point -- Boolean: `true` 或 `false` +- 数值:整数或浮点数 +- Boolean:`true` 或 `false` 例如,下面是一个有效的元数据格式: @@ -345,20 +344,20 @@ TiDB 向量存储中的每个文档都可以与元数据配对,元数据的结 ### 元数据过滤器语法 -可用的过滤器包括: +可用的过滤器包括: -- `$or`: 选择符合任意一个指定条件的向量。 -- `$and`: 选择符合所有指定条件的向量。 -- `$eq`: 等于指定值。 -- `$ne`: 不等于指定值。 -- `$gt`: 大于指定值。 -- `$gte`: 大于或等于指定值。 -- `$lt`: 小于指定值。 -- `$lte`: 小于或等于指定值。 -- `$in`: 在指定的值数组中。 -- `$nin`: 不在指定值数组中。 +- `$or`:选择符合任意一个指定条件的向量。 +- `$and`:选择符合所有指定条件的向量。 +- `$eq`:等于指定值。 +- `$ne`:不等于指定值。 +- `$gt`:大于指定值。 +- `$gte`:大于或等于指定值。 +- `$lt`:小于指定值。 +- `$lte`:小于或等于指定值。 +- `$in`:在指定的值数组中。 +- `$nin`:不在指定值数组中。 -如果文档的元数据如下: +假如一个文档的元数据如下: ```json { @@ -367,7 +366,7 @@ TiDB 向量存储中的每个文档都可以与元数据配对,元数据的结 } ``` -以下元数据筛选器可与本文档匹配: +以下元数据筛选器均可匹配到该文档: ```json { "page": 12 } @@ -400,11 +399,11 @@ TiDB 向量存储中的每个文档都可以与元数据配对,元数据的结 } ``` -元数据过滤器中的每个键值对都被视为一个单独的过滤器子句,这些子句使用 `AND` 逻辑操作符进行组合。 +TiDB 会将元数据过滤器中的每个键值对视为一个独立的过滤条件,并使用 `AND` 逻辑操作符将这些条件组合起来。 -### 例子 +### 示例 -下面的示例向 `TiDBVectorStore` 添加了两个文档,并为每个文档添加了一个 `title` 字段作为元数据: +以下示例代码向 `TiDBVectorStore` 添加了两个文档,并为每个文档添加了一个 `title` 字段作为元数据: ```python vector_store.add_texts( @@ -448,21 +447,21 @@ TiDB Vector offers advanced, high-speed vector processing capabilities, enhancin -------------------------------------------------------------------------------- ``` -## 高级用法案例: 旅行代理 +## 进阶用法示例:旅行代理 -本节演示了在旅行代理的场景下,在 Langchain 中使用 TiDB 向量搜索的案例。在案例中,我们的目的是为寻找具有特定设施 (如干净的休息室和素食选择) 的机场的客户创建个性化的旅行报告。 +本节演示如何将 Langchain 和 TiDB 向量搜索相结合,应用于旅行代理的场景。该场景的目标是为客户创建个性化的旅行报告,帮助他们找到具备特定设施(例如干净的休息室和素食选项)的机场。 -该过程包括两个主要步骤: +该示例包括两个主要步骤: -1. 在机场介绍中进行语义搜索,找出与所需设施相匹配的机场代码。 -2. 执行 SQL 查询,将这些代码与航线信息合并,突出显示符合用户偏好的航空公司和目的地。 +1. 对机场介绍中进行语义搜索,以找出符合所需设施的机场代码。 +2. 执行 SQL 查询,将这些代码与航线信息相结合,以便突出显示符合用户偏好的航空公司和目的地。 ### 准备数据 首先,创建一个表来存储机场航线数据: ```python -# 创建表格以存储飞机数据。 +# 创建表格以存储飞行计划数据。 vector_store.tidb_vector_client.execute( """CREATE TABLE airplan_routes ( id INT AUTO_INCREMENT PRIMARY KEY, @@ -520,7 +519,7 @@ vector_store.add_texts( ### 执行语义搜索 -下面的代码可以搜索到有清洁设施和素食选择的机场: +以下代码可以搜索到有清洁设施和素食选择的机场: ```python retriever = vector_store.as_retriever( @@ -603,7 +602,7 @@ airport_details.get("result") (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.')] ``` -### 清理 +### 清理数据 最后,删除创建的表,清理资源: From bb7ce0b30670a719356116d1c44daa06bfe736de Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 9 Sep 2024 15:56:47 +0800 Subject: [PATCH 027/109] overview and limitation: refine descriptions --- vector-search-integration-overview.md | 16 ++++++++-------- vector-search-limitations.md | 12 ++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index af69efdfe760..f561778e8356 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -1,30 +1,30 @@ --- -title: 向量搜索集成概述 -summary: TiDB 向量搜索集成概述,包括支持的 AI 框架、嵌入模型和 ORM 库。 +title: 向量搜索集成概览 +summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库。 --- -# 向量搜索集成概述 +# 向量搜索集成概览 -本文档概述了 TiDB 向量搜索集成,包括支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 +本文档介绍了 TiDB 向量搜索支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 ## AI 框架 -TiDB 目前支持以下 AI 框架,你能够在以下 AI 框架中使用 TiDB 向量搜索构建 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 完成其他需求,例如用于 AI 应用的文档存储和知识图谱存储等。 +此外,你还可以使用 TiDB 完成其它需求,例如将 TiDB 用于 AI 应用程序的文档存储和知识图谱存储等。 ## 嵌入模型和服务 -TiDB 向量搜索支持存储多达 16,383 维的向量,可适应大多数嵌入模型。 +TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌入模型。 你可以使用自行部署的开源嵌入模型或第三方嵌入模型提供商的嵌入 API 来生成向量。 -下表列出了一些主流嵌入模型服务提供商和相应的集成教程。 +下表列出了部分主流嵌入模型服务提供商和相应的集成教程。 | 嵌入模型服务提供商 | 教程 | |-----------------------------|---------------------------------------------------------------------------------------------------------------------| diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 6bded94b942d..5c0af31dc65e 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -1,20 +1,16 @@ --- title: 向量搜索限制 -summary: 本文介绍 TiDB 的向量搜索限制。 +summary: 了解 TiDB 向量搜索功能的限制。 --- # 向量搜索限制 -本文档介绍 TiDB 向量搜索的已知限制。我们会持续新增更多功能来提升使用体验。 +本文档介绍 TiDB 向量搜索的已知限制。在未来的版本中,我们会持续新增更多功能来提升使用体验。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 目前,向量数据类型不能存储双精度浮点数。计划在未来的版本中支持这一功能。在此期间,如果为向量数据类型导入双精度浮点数,它们将被转换为单精度数。 - +- 目前,向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量字段插入或存储数据时,如果这些数据的类型是双精度浮点数,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 ## 反馈 -我们非常重视您的反馈意见,并随时准备为您提供帮助: - -- [Join our Discord](https://discord.gg/zcqexutz2R) -- [Visit our Support Portal](https://tidb.support.pingcap.com/) \ No newline at end of file +我们非常重视您的反馈意见。如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file From d50b63869fc73f251261b68d90f3efd19b89287b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 10 Sep 2024 10:38:37 +0800 Subject: [PATCH 028/109] add vector index doc introduction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-improve-performance.md | 37 ++++ vector-search-index.md | 273 +++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 vector-search-improve-performance.md create mode 100644 vector-search-index.md diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md new file mode 100644 index 000000000000..72941e987431 --- /dev/null +++ b/vector-search-improve-performance.md @@ -0,0 +1,37 @@ +--- +title: 优化向量搜索性能 +summary: 了解提高 TiDB 向量搜索性能的最佳实践。 +--- + +# 优化向量搜索性能 + +TiDB 向量搜索允许你执行 ANN 查询,搜索与图像、文档等相似的结果。要提高查询性能,请参考以下最佳实践。 + +## 为向量列添加向量搜索索引 + +[向量搜索索引](/vector-search-index.md) 可显著提高向量搜索查询的性能,通常提高 10 倍或更多,而召回率仅略有下降。 + +## 确保向量索引的完全构建 + +向量索引是异步建立的。在所有向量数据都编入索引之前,向量搜索性能不会达到最佳。要查看索引构建进度,可参阅 [查看索引构建进度](/vector-search-index.md#view-index-build-progress)。 + +## 减少向量维数或缩短嵌入时间 + +向量搜索索引和查询的计算复杂度会随着向量大小的增加而显著提高,从而需要进行更多的浮点比较。 + +To optimize performance, consider reducing the vector dimensions whenever feasible. This usually needs switching to another embedding model. Make sure to measure the impact of changing embedding models on the accuracy of your vector queries. +为了优化性能,在可行的情况下应考虑减少向量维度,这通常需要切换到另一种嵌入模型。你需要确保改变嵌入模型对向量查询准确性的影响。 + +某些嵌入模型,如 OpenAI `text-embedding-3-large` 支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失嵌入的概念表示特性的情况下,从向量序列末尾删除一些数字。你也可以使用这种嵌入模型来减少向量维数。 + +## 在结果输出中排除向量列 + +向量嵌入数据通常很大,而且只在搜索过程中使用。通过从查询结果中排除向量列,可以大大减少在 TiDB 服务器和 SQL 客户端之间传输的数据量,从而提高查询性能。 + +要排除向量列,请在 `SELECT` 语句中明确列出要检索的列,而不是使用 `SELECT *`。 + +## 预热索引 + +当索引被冷访问时,从 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..fba97353feec --- /dev/null +++ b/vector-search-index.md @@ -0,0 +1,273 @@ +--- +title: 向量搜索索引 +summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (KNN) 查询 +--- + +# 向量搜索索引 + +K 近邻 (KNN) 搜索是在向量空间中找到距离给定向量最近的 K 个向量的查询。要找到最近的 K 个向量,最直接的方法就是暴力搜索,即计算向量空间中所有点与给定向量之间的距离。这种方法拥有最好的精确度,但在实际的搜索中,往往搜索速度太慢。因此,近邻搜索问题通常采用近似算法来解决。 + +在 TiDB 中,你可以创建并利用向量搜索索引来对 [向量类型](/vector-search-data-types.md) 的列进行近似近邻 (ANN) 搜索。通过使用向量搜索索引,整个查询可在几毫秒内完成。 + +TiDB 目前支持以下向量搜索索引算法: + +- HNSW + + +## 创建 HNSW 向量搜索索引 + +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是最流行的向量搜索索引算法。HNSW 索引的性能良好,且准确率相对较高 (特定情况下可达 98%), + +要创建 HNSW 向量搜索索引,你可以在创建表格时,在 [向量数据类型](/vector-search-data-types.md) 列的注释中指定索引定义: + +```sql +CREATE TABLE vector_table_with_index ( + id INT PRIMARY KEY, doc TEXT, + embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" +); +``` + +> **Note:** +> +> 创建向量索引的语法可能在今后的版本中发生变化。 + +创建向量索引时,需要通过 `distance=` 配置指定距离度量: + +- 余弦距离: `COMMENT "hnsw(distance=cosine)"` +- L2 距离: `COMMENT "hnsw(distance=l2)"` + +The vector index can only be created for fixed-dimensional vector columns like `VECTOR(3)`. It cannot be created for mixed-dimensional vector columns like `VECTOR` because vector distances can only be calculated between vectors with the same dimensions. +只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引。它不能为混合维度的向量列 (如 `VECTOR` ) 创建,因为向量距离只能在具有相同维度的向量之间计算。 + +如果你使用的是编程语言 SDK 或 ORM,请参阅以下文档以创建向量索引: + +- Python: [TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) +- Python: [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) +- Python: [Peewee](/vector-search-integrate-with-peewee.md) +- Python: [Django](/vector-search-integrate-with-django-orm.md) + +创建向量索引时请注意以下限制。这些限制可能会在今后的版本中取消: + +- 向量索引暂不支持 L1 距离和内积。 + +- 只有在创建表时才能定义和创建矢量索引。创建表后,不能使用 DDL 语句创建矢量索引。也不能使用 DDL 语句删除矢量索引。 + + +## 使用向量搜索索引 + +在 K 近邻搜索查询中,可以使用 `ORDER BY ... LIMIT` 形式来使用向量搜索索引,如下所示: + +```sql +SELECT * +FROM vector_table_with_index +ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +LIMIT 10 +``` + +如果要在向量搜索中使用索引,则必须使用与创建向量索引时所定义的相同的距离度量。 + +## 使用带过滤器的向量搜索索引 + +包含预过滤 (使用 `WHERE` 子句) 的查询不能使用向量搜索索引,因为它们不是根据 SQL 语义查询的 K 近邻。例如 + +```sql +-- 过滤器在 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 +-- 过滤器在 kNN 之前执行,因此不能使用向量索引: +SELECT * FROM docs +WHERE ver = "v2.0" +ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +LIMIT 5; +``` + +与其使用 `WHERE` 子句编写查询,不如对表进行分区,然后使用 [`PARTITION` 关键字](/partitioned-table.md#partition-selection) 在分区内进行查询: + +```sql +CREATE TABLE docs ( + id INT, + ver VARCHAR(10), + doc TEXT, + embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" +) 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)。 + +## 检查是否使用了向量搜索索引 + +使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 或 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句检查该查询是否使用了向量搜索索引。当 `annIndex:` 出现在 `TableFullScan` 执行计划的 `operator info` 列中时,表示该表扫描使用了向量搜索索引。 + +**示例:使用向量索引** + +```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) +``` + +当无法使用向量搜索索引时,在某些情况下会出现警告,以帮助你了解原因: + +```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}},...} | | ++-----+--------------------------------------------------------+-----+ +``` + +> **Note:** +> +> 执行信息为内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 + +一些重要字段的解释: + +- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个矢量索引。 +- `vector_index.load.from_s3`: 从 S3 加载的索引数量。 +- `vector_index.load.from_disk`: 从磁盘加载的索引数量。索引之前已从 S3 下载。 +- `vector_index.load.from_cache`: 从缓存中加载的索引数量。索引之前已从 S3 下载。 +- `vector_index.search.total`: 在索引中搜索的总持续时间。延迟大通常意味着索引是冷索引(以前从未被访问过,或很久以前被访问过),因此在索引中搜索时会产生大量 IO。这个字段可能大于实际查询时间,因为可能会并行搜索多个矢量索引。 +- `vector_index.search.discarded_nodes`: 在搜索过程中已访问但被丢弃的向量行数。搜索结果不会考虑这些被丢弃的向量。如果数值较大,通常表示有很多由 UPDATE 或 DELETE 语句引起的陈旧行。 + +请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [EXPLAIN Walkthrough](/explain-walkthrough.md) 来解释输出结果。 + +## See also + +- [优化向量搜索性能](/vector-search-improve-performance.md) +- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file From 52909469457240ff6788dabc925ea7c9fb2be5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 10 Sep 2024 16:40:53 +0800 Subject: [PATCH 029/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 1c82f0c06b2e..dafdd1ec1afb 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -55,20 +55,23 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量,以下是各个变量的含义: -- `HOST`:TiDB 集群的主机号。 -- `PORT`:TiDB 集群的端口。 -- `USERNAME`:连接 TiDB 集群的用户名。 -- `PASSWORD`:连接 TiDB 集群的密码。 -- `DATABASE`:要连接的数据库名称。 -- `CA_PATH`:根证书文件的路径。 +- ``:TiDB 集群的主机号。 +- ``:TiDB 集群的端口。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 +- ``:根证书文件的路径。 以下为 MacOS 的示例: ```dotenv -TIDB_DATABASE_URL="mysql+pymysql://.root:@:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" +TIDB_DATABASE_URL="mysql+pymysql://:@:/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" ``` +> **Tip:** + > + > `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
From eb604f7c08e0754b8f0bfc26b3f75522cf363d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 10 Sep 2024 17:51:20 +0800 Subject: [PATCH 030/109] modify introduction of self-hosted tidb connection type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 6 +-- vector-search-integrate-with-django-orm.md | 3 ++ ...-search-integrate-with-jinaai-embedding.md | 41 +++++++++++-------- vector-search-integrate-with-langchain.md | 16 +++++--- vector-search-integrate-with-llamaindex.md | 8 +++- vector-search-integrate-with-peewee.md | 23 ++++++----- vector-search-integrate-with-sqlalchemy.md | 24 ++++++----- 7 files changed, 73 insertions(+), 48 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index dafdd1ec1afb..29b68d4bc62e 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -55,7 +55,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量,以下是各个变量的含义: +在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量,将连接字符串复制到 `.env` 文件中。以下是各个变量的含义: - ``:TiDB 集群的主机号。 - ``:TiDB 集群的端口。 @@ -70,8 +70,8 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv TIDB_DATABASE_URL="mysql+pymysql://:@:/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" ``` > **Tip:** - > - > `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> +> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 14ac55152f75..6b0f6e1376e7 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -93,6 +93,9 @@ TIDB_PASSWORD=******** TIDB_DATABASE=test TIDB_CA_PATH=/etc/ssl/cert.pem ``` +> **Tip:** +> +> `TIDB_CA_PATH` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 3d426144837b..ce0698cd815a 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -62,32 +62,41 @@ pip install -r requirements.txt
-1. 在项目的根目录下新建一个 `.env` 文件: +1. 在项目的根目录下新建一个 `.env` 文件,将以下内容复制进去: ```dotenv - - TIDB_HOST='{host}' - - TIDB_PORT='4000' - - TIDB_USER='root' - - TIDB_PASSWORD='{password}' - - TIDB_DB_NAME='test' + export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" ``` - 注意替换 `{}` 中的占位符为你的 TiDB 实际对应的值,并删除 CA_PATH 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。 + 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: -2. 在终端中设置环境变量: + - `HOST`:TiDB 集群的主机号。 + - `PORT`:TiDB 集群的端口号。 + - `USERNAME`:连接 TiDB 集群的用户名。 + - `PASSWORD`:连接 TiDB 集群的密码。 + - `DATABASE`:要连接的数据库名称。 + - `CA`:根证书文件的路径。 - ```dotenv - JINAAI_API_KEY="****" - TIDB_DATABASE_URL="{tidb_connection_string}" - ``` - 以下为 MacOS 的示例: +2. 或者,你也可以通过在终端中直接设置环境变量以连接 TiDB 集群: - ```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" + ```shell + export JINA_API_KEY="****" + export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" ``` + 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: + + - `HOST`:TiDB 集群的主机号。 + - `PORT`:TiDB 集群的端口号。 + - `USERNAME`:连接 TiDB 集群的用户名。 + - `PASSWORD`:连接 TiDB 集群的密码。 + - `DATABASE`:要连接的数据库名称。 + - `CA`:根证书文件的路径。 + +> **Tip:** +> +> `CA` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 - 注意替换其中的占位符为你的 TiDB 实际对应的值。
diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index f478a4e95472..d256f4884841 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -42,10 +42,10 @@ touch integrate_with_langchain.ipynb 在你的项目目录下,运行以下命令安装所需的软件包: ```shell -!pip install langchain langchain-community -!pip install langchain-openai -!pip install pymysql -!pip install tidb-vector +pip install langchain langchain-community +pip install langchain-openai +pip install pymysql +pip install tidb-vector ``` 在 Jupyter Notebook 中打开 `integrate_with_langchain.ipynb` 文件,添加以下代码以导入所需的软件包: @@ -86,6 +86,10 @@ TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..p 注意替换为你的 TiDB 实际对应的值。 +> **Tip:** +> +> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +
@@ -137,8 +141,8 @@ TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..p 在你的项目目录中创建一个名为 `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' +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 加载并分割文档 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index d7820e39caa7..b10aec261492 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -85,6 +85,10 @@ TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..p 注意替换为你的 TiDB 实际对应的值。 +> **Tip:** +> +> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +
@@ -136,8 +140,8 @@ TIDB_DATABASE_URL="mysql+pymysql://.root:@gateway01..p 在你的项目目录中创建一个名为 `data/paul_graham/` 的目录,然后从 [run-llama/llama_index](https://github.com/run-llama/llama_index) 代码库中下载样本文档 [`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' +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 加载文档 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index ac6994eb2e24..4cb188247f3d 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -64,7 +64,16 @@ pip install peewee pymysql python-dotenv tidb-vector
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 +在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制进 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 + +```shell +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 +``` - `TIDB_HOST`: TiDB 集群的主机号。 - `TIDB_PORT`: TiDB 集群的端口号。 @@ -73,16 +82,10 @@ pip install peewee pymysql python-dotenv tidb-vector - `TIDB_DATABASE`: 要连接的数据库名称。 - `TIDB_CA_PATH`: 根证书文件的路径。 -以下为 MacOS 的示例: -```dotenv -TIDB_HOST=127.0.0.1 -TIDB_PORT=4000 -TIDB_USERNAME=********.root -TIDB_PASSWORD=******** -TIDB_DATABASE=test -TIDB_CA_PATH=/etc/ssl/cert.pem -``` +> **Tip:** +> +> `TIDB_CA_PATH` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index b299c55ba3b2..f1589e9f9ffe 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -64,20 +64,22 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 +在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制到 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 -- `HOST`:TiDB 集群的主机。 -- `PORT`:TiDB 集群的端口。 -- `USERNAME`:连接 TiDB 集群的用户名。 -- `PASSWORD`:连接 TiDB 集群的密码。 -- `DATABASE`:要连接的数据库名称。 -- `CA`:根证书文件的路径。 +```shell +TIDB_DATABASE_URL=mysql+pymysql://:@:/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true +``` -以下为 MacOS 的示例: +- ``:TiDB 集群的主机。 +- ``:TiDB 集群的端口。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。 +- ``:根证书文件的路径。 -```dotenv -TIDB_DATABASE_URL="mysql+pymysql://.root:@127.0.0.1:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true" -``` +> **Tip:** +> +> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
From 65656f8b9edddeb237b0e619bf82f2573bb733ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 11:13:39 +0800 Subject: [PATCH 031/109] modify tidb connection when using tidb self-hosted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 5 ++--- vector-search-integrate-with-django-orm.md | 4 +--- vector-search-integrate-with-jinaai-embedding.md | 15 ++++++--------- vector-search-integrate-with-langchain.md | 8 ++++---- vector-search-integrate-with-llamaindex.md | 8 ++------ vector-search-integrate-with-peewee.md | 6 ++---- vector-search-integrate-with-sqlalchemy.md | 5 ++--- 7 files changed, 19 insertions(+), 32 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 29b68d4bc62e..84ce173abcf2 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -62,16 +62,15 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 - ``:要连接的数据库名称。 -- ``:根证书文件的路径。 以下为 MacOS 的示例: ```dotenv -TIDB_DATABASE_URL="mysql+pymysql://:@:/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" +TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` > **Tip:** > -> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> `` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。
diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 6b0f6e1376e7..48ffffbd6539 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -81,7 +81,6 @@ pip install Django django-tidb mysqlclient numpy python-dotenv - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 - `TIDB_PASSWORD`:连接 TiDB 集群的密码。 - `TIDB_DATABASE`:要连接的数据库名称。 -- `TIDB_CA_PATH`:根证书文件的路径。 以下为 MacOS 的示例: @@ -91,11 +90,10 @@ TIDB_PORT=4000 TIDB_USERNAME=********.root TIDB_PASSWORD=******** TIDB_DATABASE=test -TIDB_CA_PATH=/etc/ssl/cert.pem ``` > **Tip:** > -> `TIDB_CA_PATH` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> `TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。
diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index ce0698cd815a..e18a00200b3b 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -65,24 +65,26 @@ pip install -r requirements.txt 1. 在项目的根目录下新建一个 `.env` 文件,将以下内容复制进去: ```dotenv - export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" + export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/" ``` - 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: + 注意替换参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: - `HOST`:TiDB 集群的主机号。 - `PORT`:TiDB 集群的端口号。 - `USERNAME`:连接 TiDB 集群的用户名。 - `PASSWORD`:连接 TiDB 集群的密码。 - `DATABASE`:要连接的数据库名称。 - - `CA`:根证书文件的路径。 +> **Tip:** +> +> `PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 2. 或者,你也可以通过在终端中直接设置环境变量以连接 TiDB 集群: ```shell export JINA_API_KEY="****" - export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true" + export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/" ``` 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: @@ -91,11 +93,6 @@ pip install -r requirements.txt - `USERNAME`:连接 TiDB 集群的用户名。 - `PASSWORD`:连接 TiDB 集群的密码。 - `DATABASE`:要连接的数据库名称。 - - `CA`:根证书文件的路径。 - -> **Tip:** -> -> `CA` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。
diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index d256f4884841..ee6eb845a117 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -81,14 +81,14 @@ os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") 例如,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" +TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` -注意替换为你的 TiDB 实际对应的值。 - > **Tip:** > -> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> 注意替换为你的 TiDB 实际对应的值。`PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 + +
diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index b10aec261492..40e15ddef49e 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -80,14 +80,10 @@ os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") 例如,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" +TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` -注意替换为你的 TiDB 实际对应的值。 - -> **Tip:** -> -> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +注意替换为你的 TiDB 实际对应的值。`PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。
diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 4cb188247f3d..1dba80313395 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -64,7 +64,7 @@ pip install peewee pymysql python-dotenv tidb-vector
-在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制进 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 +在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制进 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 ```shell TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com @@ -72,7 +72,6 @@ TIDB_PORT=4000 TIDB_USERNAME=******.root TIDB_PASSWORD=******** TIDB_DATABASE=test -TIDB_CA_PATH=/etc/ssl/cert.pem ``` - `TIDB_HOST`: TiDB 集群的主机号。 @@ -80,12 +79,11 @@ TIDB_CA_PATH=/etc/ssl/cert.pem - `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 - `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 - `TIDB_DATABASE`: 要连接的数据库名称。 -- `TIDB_CA_PATH`: 根证书文件的路径。 > **Tip:** > -> `TIDB_CA_PATH` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> 注意替换为你的 TiDB 实际对应的值。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。
diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index f1589e9f9ffe..d92d02eafe24 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -67,7 +67,7 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector 在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制到 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 ```shell -TIDB_DATABASE_URL=mysql+pymysql://:@:/?ssl_ca=&ssl_verify_cert=true&ssl_verify_identity=true +TIDB_DATABASE_URL=mysql+pymysql://:@:/ ``` - ``:TiDB 集群的主机。 @@ -75,11 +75,10 @@ TIDB_DATABASE_URL=mysql+pymysql://:@:/ - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 - ``:要连接的数据库名称。 -- ``:根证书文件的路径。 > **Tip:** > -> `ssl_ca` 可以无需指定,这样可以匹配到 Linux 和 Windows 上,即 Python SDK 解决 SSL 证书问题。 +> 注意替换为你的 TiDB 实际对应的值。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。
From 99f9ab7dbdb284b4c53a79797360883576592b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 13:17:43 +0800 Subject: [PATCH 032/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 33 ++++++++++++++++--- ...-search-integrate-with-jinaai-embedding.md | 4 +-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index fba97353feec..5c4487d4683c 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -18,15 +18,30 @@ TiDB 目前支持以下向量搜索索引算法: [HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是最流行的向量搜索索引算法。HNSW 索引的性能良好,且准确率相对较高 (特定情况下可达 98%), -要创建 HNSW 向量搜索索引,你可以在创建表格时,在 [向量数据类型](/vector-search-data-types.md) 列的注释中指定索引定义: +要创建 HNSW 向量搜索索引,你可以在创建表格时,使用以下语法指定为哪一列的[向量数据类型](/vector-search-data-types.md)构建索引: ```sql -CREATE TABLE vector_table_with_index ( - id INT PRIMARY KEY, doc TEXT, - embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" +CREATE TABLE foo ( + id INT PRIMARY KEY, + data VECTOR(5), + data64 VECTOR64(10), + VECTOR INDEX data USING HNSW ((VEC_COSINE_DISTANCE(data))) ); ``` +如果已经创建了带有向量数据类型的表格,你可以通过 `ALTER TABLE` 的语法为向量数据创建索引,示例如下: + +```sql +CREATE VECTOR INDEX idx ON t ((VEC_COSINE_DISTANCE(a))) USING HNSW; +CREATE VECTOR INDEX IF NOT EXISTS idx ON t ((VEC_COSINE_DISTANCE(a))) TYPE HNSW; +CREATE VECTOR INDEX ident ON db.t (ident, ident ASC ) TYPE HNSW; + +ALTER TABLE t ADD VECTOR ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; +ALTER TABLE t ADD VECTOR KEY ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; +ALTER TABLE t ADD VECTOR INDEX ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; +ALTER TABLE t ADD VECTOR INDEX IF NOT EXISTS ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; +``` + > **Note:** > > 创建向量索引的语法可能在今后的版本中发生变化。 @@ -36,7 +51,6 @@ CREATE TABLE vector_table_with_index ( - 余弦距离: `COMMENT "hnsw(distance=cosine)"` - L2 距离: `COMMENT "hnsw(distance=l2)"` -The vector index can only be created for fixed-dimensional vector columns like `VECTOR(3)`. It cannot be created for mixed-dimensional vector columns like `VECTOR` because vector distances can only be calculated between vectors with the same dimensions. 只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引。它不能为混合维度的向量列 (如 `VECTOR` ) 创建,因为向量距离只能在具有相同维度的向量之间计算。 如果你使用的是编程语言 SDK 或 ORM,请参阅以下文档以创建向量索引: @@ -267,6 +281,15 @@ LIMIT 10; 请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [EXPLAIN Walkthrough](/explain-walkthrough.md) 来解释输出结果。 +## 向量搜索索引的约束 + +- TiDB 集群需要创建 TiFlash 的副本 +- 不能是主键索引 +- 不能是复合索引 +- 不可以为同一列创建多个向量索引 +- 向量索引需要指定距离函数(目前只支持 `余弦距离` 和 `L2 距离`) +- 不支持删除具有向量索引的列,也不支持同时创建多个索引。 + ## See also - [优化向量搜索性能](/vector-search-improve-performance.md) diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index e18a00200b3b..c7e16121dfc1 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -65,7 +65,7 @@ pip install -r requirements.txt 1. 在项目的根目录下新建一个 `.env` 文件,将以下内容复制进去: ```dotenv - export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/" + export TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` 注意替换参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: @@ -84,7 +84,7 @@ pip install -r requirements.txt ```shell export JINA_API_KEY="****" - export TIDB_DATABASE_URL="mysql+pymysql://:@:4000/" + export TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: From 2c5efa430faedee8df180a450e6548a9e38a6968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 13:21:06 +0800 Subject: [PATCH 033/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- ...-search-integrate-with-jinaai-embedding.md | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index c7e16121dfc1..06056ee070a9 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -62,13 +62,14 @@ pip install -r requirements.txt
-1. 在项目的根目录下新建一个 `.env` 文件,将以下内容复制进去: +你可以通过在终端中直接设置环境变量以连接 TiDB 集群: - ```dotenv + ```shell + export JINA_API_KEY="****" export TIDB_DATABASE_URL="mysql+pymysql://:@:/" - ``` - - 注意替换参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: + ``` + + 注意替换参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: - `HOST`:TiDB 集群的主机号。 - `PORT`:TiDB 集群的端口号。 @@ -80,21 +81,6 @@ pip install -r requirements.txt > `PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 -2. 或者,你也可以通过在终端中直接设置环境变量以连接 TiDB 集群: - - ```shell - export JINA_API_KEY="****" - export TIDB_DATABASE_URL="mysql+pymysql://:@:/" - ``` - 注意替换参数为你的 TiDB 实际对应的值,并删除 `CA` 这行。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: - - - `HOST`:TiDB 集群的主机号。 - - `PORT`:TiDB 集群的端口号。 - - `USERNAME`:连接 TiDB 集群的用户名。 - - `PASSWORD`:连接 TiDB 集群的密码。 - - `DATABASE`:要连接的数据库名称。 - -
From b2e32b70c273620d206ce7314abbfaf2a5727490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 13:31:29 +0800 Subject: [PATCH 034/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 5c4487d4683c..ca2ba563f5ef 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -46,10 +46,10 @@ ALTER TABLE t ADD VECTOR INDEX IF NOT EXISTS ((VEC_COSINE_DISTANCE(a))) USING HN > > 创建向量索引的语法可能在今后的版本中发生变化。 -创建向量索引时,需要通过 `distance=` 配置指定距离度量: +创建向量索引时,需要通过 `HNSW ((distance_metric(cols_name)))` 配置指定距离度量: -- 余弦距离: `COMMENT "hnsw(distance=cosine)"` -- L2 距离: `COMMENT "hnsw(distance=l2)"` +- 余弦距离: `HNSW ((VEC_COSINE_DISTANCE(cols_name)))` +- L2 距离: `HNSW ((VEC_L2_DISTANCE(cols_name)))` 只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引。它不能为混合维度的向量列 (如 `VECTOR` ) 创建,因为向量距离只能在具有相同维度的向量之间计算。 From 9a51513bc219769c56ba980edb2a715222f675c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 14:24:06 +0800 Subject: [PATCH 035/109] shorten index example case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index ca2ba563f5ef..81917995faeb 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -32,14 +32,9 @@ CREATE TABLE foo ( 如果已经创建了带有向量数据类型的表格,你可以通过 `ALTER TABLE` 的语法为向量数据创建索引,示例如下: ```sql -CREATE VECTOR INDEX idx ON t ((VEC_COSINE_DISTANCE(a))) USING HNSW; -CREATE VECTOR INDEX IF NOT EXISTS idx ON t ((VEC_COSINE_DISTANCE(a))) TYPE HNSW; -CREATE VECTOR INDEX ident ON db.t (ident, ident ASC ) TYPE HNSW; - -ALTER TABLE t ADD VECTOR ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; -ALTER TABLE t ADD VECTOR KEY ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; -ALTER TABLE t ADD VECTOR INDEX ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; -ALTER TABLE t ADD VECTOR INDEX IF NOT EXISTS ((VEC_COSINE_DISTANCE(a))) USING HNSW COMMENT 'a'; +CREATE VECTOR INDEX idx_name USING HNSW ON foo ((VEC_COSINE_DISTANCE(data))) + +ALTER TABLE foo ADD VECTOR INDEX idx_name USING HNSW ((VEC_COSINE_DISTANCE(data))) ``` > **Note:** From c09d85f1c3297ba50032ee351edb0903d330607f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 11 Sep 2024 14:40:39 +0800 Subject: [PATCH 036/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 81917995faeb..d73d44ff585c 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -55,12 +55,7 @@ ALTER TABLE foo ADD VECTOR INDEX idx_name USING HNSW ((VEC_COSINE_DISTANCE(data) - Python: [Peewee](/vector-search-integrate-with-peewee.md) - Python: [Django](/vector-search-integrate-with-django-orm.md) -创建向量索引时请注意以下限制。这些限制可能会在今后的版本中取消: - -- 向量索引暂不支持 L1 距离和内积。 - -- 只有在创建表时才能定义和创建矢量索引。创建表后,不能使用 DDL 语句创建矢量索引。也不能使用 DDL 语句删除矢量索引。 - +有关向量搜索索引的相关约束和限制,请参阅 [向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束) ## 使用向量搜索索引 @@ -267,11 +262,11 @@ LIMIT 10; 一些重要字段的解释: -- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个矢量索引。 +- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个向量索引。 - `vector_index.load.from_s3`: 从 S3 加载的索引数量。 - `vector_index.load.from_disk`: 从磁盘加载的索引数量。索引之前已从 S3 下载。 - `vector_index.load.from_cache`: 从缓存中加载的索引数量。索引之前已从 S3 下载。 -- `vector_index.search.total`: 在索引中搜索的总持续时间。延迟大通常意味着索引是冷索引(以前从未被访问过,或很久以前被访问过),因此在索引中搜索时会产生大量 IO。这个字段可能大于实际查询时间,因为可能会并行搜索多个矢量索引。 +- `vector_index.search.total`: 在索引中搜索的总持续时间。延迟大通常意味着索引是冷索引(以前从未被访问过,或很久以前被访问过),因此在索引中搜索时会产生大量 IO。这个字段可能大于实际查询时间,因为可能会并行搜索多个向量索引。 - `vector_index.search.discarded_nodes`: 在搜索过程中已访问但被丢弃的向量行数。搜索结果不会考虑这些被丢弃的向量。如果数值较大,通常表示有很多由 UPDATE 或 DELETE 语句引起的陈旧行。 请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [EXPLAIN Walkthrough](/explain-walkthrough.md) 来解释输出结果。 @@ -284,6 +279,7 @@ LIMIT 10; - 不可以为同一列创建多个向量索引 - 向量索引需要指定距离函数(目前只支持 `余弦距离` 和 `L2 距离`) - 不支持删除具有向量索引的列,也不支持同时创建多个索引。 +- 不支持对向量索引设置 `invisible` 操作。 ## See also From bf063b729354b138b1d421762c8b42142fa5fdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 12 Sep 2024 13:42:14 +0800 Subject: [PATCH 037/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-get-started-using-python.md | 1 + vector-search-integrate-with-django-orm.md | 4 ++-- vector-search-integrate-with-jinaai-embedding.md | 1 + vector-search-integrate-with-langchain.md | 1 + vector-search-integrate-with-llamaindex.md | 1 + vector-search-integrate-with-peewee.md | 6 +++--- vector-search-integrate-with-sqlalchemy.md | 1 + 7 files changed, 10 insertions(+), 5 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 84ce173abcf2..4995de2278bd 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -66,6 +66,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv 以下为 MacOS 的示例: ```dotenv +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` > **Tip:** diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 48ffffbd6539..9c7ce2f86691 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -87,8 +87,8 @@ pip install Django django-tidb mysqlclient numpy python-dotenv ```dotenv TIDB_HOST=127.0.0.1 TIDB_PORT=4000 -TIDB_USERNAME=********.root -TIDB_PASSWORD=******** +TIDB_USERNAME=root +TIDB_PASSWORD= TIDB_DATABASE=test ``` > **Tip:** diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 06056ee070a9..d51fe467aa8a 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -66,6 +66,7 @@ pip install -r requirements.txt ```shell export JINA_API_KEY="****" + # 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" export TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index ee6eb845a117..c103eca4102a 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -81,6 +81,7 @@ os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") 例如,macOS 上的连接字符串如下所示: ```dotenv +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 40e15ddef49e..ecdc1be6f667 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -80,6 +80,7 @@ os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") 例如,macOS 上的连接字符串如下所示: ```dotenv +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL="mysql+pymysql://:@:/" ``` diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 1dba80313395..d06e1e52f38d 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -67,10 +67,10 @@ pip install peewee pymysql python-dotenv tidb-vector 在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制进 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 ```shell -TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com +TIDB_HOST=127.0.0.1 TIDB_PORT=4000 -TIDB_USERNAME=******.root -TIDB_PASSWORD=******** +TIDB_USERNAME=root +TIDB_PASSWORD= TIDB_DATABASE=test ``` diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index d92d02eafe24..5650b5bb2cb5 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -67,6 +67,7 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector 在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制到 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 ```shell +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL=mysql+pymysql://:@:/ ``` From 9eaf1f7da9285a1b54160e82c5fc468e504c6250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Fri, 13 Sep 2024 10:00:29 +0800 Subject: [PATCH 038/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-improve-performance.md | 1 - 1 file changed, 1 deletion(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 72941e987431..ae14ef505bbf 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -19,7 +19,6 @@ TiDB 向量搜索允许你执行 ANN 查询,搜索与图像、文档等相似 向量搜索索引和查询的计算复杂度会随着向量大小的增加而显著提高,从而需要进行更多的浮点比较。 -To optimize performance, consider reducing the vector dimensions whenever feasible. This usually needs switching to another embedding model. Make sure to measure the impact of changing embedding models on the accuracy of your vector queries. 为了优化性能,在可行的情况下应考虑减少向量维度,这通常需要切换到另一种嵌入模型。你需要确保改变嵌入模型对向量查询准确性的影响。 某些嵌入模型,如 OpenAI `text-embedding-3-large` 支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失嵌入的概念表示特性的情况下,从向量序列末尾删除一些数字。你也可以使用这种嵌入模型来减少向量维数。 From c62f7c9fd070940ad3cd66b62011f8777e82ac35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Fri, 13 Sep 2024 11:41:44 +0800 Subject: [PATCH 039/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index d73d44ff585c..e644f97e1733 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -120,7 +120,8 @@ CREATE TABLE docs ( id INT, ver VARCHAR(10), doc TEXT, - embedding VECTOR(3) COMMENT "hnsw(distance=cosine)" + embedding VECTOR(3), + VECTOR INDEX 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'), From 0083ea1b234b3613b6c6c091d77bb59ca6e1f122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Fri, 13 Sep 2024 13:28:57 +0800 Subject: [PATCH 040/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 2 +- vector-search-index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index f5e0981b765b..146fa67db45d 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -209,7 +209,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 向量也可以显式地转换为字符串。以使用 `VEC_AS_TEXT()` 函数为例: ```sql --- 字符串首先被隐式地转换成向量,然后被显示地转为字符串,因而返回了一个规范化的字符串格式: +-- 字符串首先被隐式地转换成向量,然后被显式地转为字符串,因而返回了一个规范化的字符串格式: [tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]'); +--------------------------------------+ | VEC_AS_TEXT('[0.3, 0.5, -0.1]') | diff --git a/vector-search-index.md b/vector-search-index.md index e644f97e1733..4aacca576232 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -277,7 +277,7 @@ LIMIT 10; - TiDB 集群需要创建 TiFlash 的副本 - 不能是主键索引 - 不能是复合索引 -- 不可以为同一列创建多个向量索引 +- 不可以为同一列创建多个相同距离函数的向量索引 - 向量索引需要指定距离函数(目前只支持 `余弦距离` 和 `L2 距离`) - 不支持删除具有向量索引的列,也不支持同时创建多个索引。 - 不支持对向量索引设置 `invisible` 操作。 From 6a673b9323a74a8eb78c3ef77020e6593d5485ca Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 13 Sep 2024 19:59:55 +0800 Subject: [PATCH 041/109] index & improve performance: refine descriptions --- vector-search-improve-performance.md | 25 +++-- vector-search-index.md | 149 ++++++++++++++------------- 2 files changed, 87 insertions(+), 87 deletions(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 72941e987431..17b232adea1c 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -1,37 +1,36 @@ --- title: 优化向量搜索性能 -summary: 了解提高 TiDB 向量搜索性能的最佳实践。 +summary: 了解优化 TiDB 向量搜索性能的最佳实践。 --- # 优化向量搜索性能 -TiDB 向量搜索允许你执行 ANN 查询,搜索与图像、文档等相似的结果。要提高查询性能,请参考以下最佳实践。 +在 TiDB 中,你可以通过向量搜索功能进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索,查找与给定的图像、文档等相似的结果。为了提升查询性能,请参考以下最佳实践。 ## 为向量列添加向量搜索索引 -[向量搜索索引](/vector-search-index.md) 可显著提高向量搜索查询的性能,通常提高 10 倍或更多,而召回率仅略有下降。 +[向量搜索索引](/vector-search-index.md)可显著提高向量搜索查询的性能,通常能提高 10 倍或更多,而召回率仅略有下降。 -## 确保向量索引的完全构建 +## 确保向量索引已完全构建 -向量索引是异步建立的。在所有向量数据都编入索引之前,向量搜索性能不会达到最佳。要查看索引构建进度,可参阅 [查看索引构建进度](/vector-search-index.md#view-index-build-progress)。 +向量搜索索引是通过异步方式构建的。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#view-index-build-progress)。 ## 减少向量维数或缩短嵌入时间 -向量搜索索引和查询的计算复杂度会随着向量大小的增加而显著提高,从而需要进行更多的浮点比较。 +随着向量大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 -To optimize performance, consider reducing the vector dimensions whenever feasible. This usually needs switching to another embedding model. Make sure to measure the impact of changing embedding models on the accuracy of your vector queries. -为了优化性能,在可行的情况下应考虑减少向量维度,这通常需要切换到另一种嵌入模型。你需要确保改变嵌入模型对向量查询准确性的影响。 +为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,请评估嵌入模型的改变将对向量查询准确性产生的影响是否可以接受。 -某些嵌入模型,如 OpenAI `text-embedding-3-large` 支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失嵌入的概念表示特性的情况下,从向量序列末尾删除一些数字。你也可以使用这种嵌入模型来减少向量维数。 +一些嵌入模型,如 OpenAI `text-embedding-3-large`,支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失向量表示的概念特征的情况下,从向量序列末尾移除一些数字。你也可以使用这种嵌入模型来减少向量维数。 ## 在结果输出中排除向量列 -向量嵌入数据通常很大,而且只在搜索过程中使用。通过从查询结果中排除向量列,可以大大减少在 TiDB 服务器和 SQL 客户端之间传输的数据量,从而提高查询性能。 +向量嵌入数据通常很大,而且只在搜索过程中使用。通过从查询结果中排除向量列,可以显著减少 TiDB 服务器和 SQL 客户端之间传输的数据量,从而提高查询性能。 -要排除向量列,请在 `SELECT` 语句中明确列出要检索的列,而不是使用 `SELECT *`。 +要从结果输出中排除向量列,请在 `SELECT` 语句中明确指定需要检索的列,而不是使用 `SELECT *` 检索所有列。 ## 预热索引 -当索引被冷访问时,从 S3 加载整个索引或从磁盘(而不是内存)加载索引都需要时间。这些过程通常会导致较高的尾部延迟。此外,如果集群上长时间(如数小时)没有 SQL 查询,计算资源就会被回收,下次就会出现冷访问。 +当访问一个从未被使用过或长时间未被使用过的索引(冷访问)时,TiDB 需要从 S3 或磁盘(而不是内存)加载整个索引。这个过程需要一定的时间,往往会导致较高的查询延迟。此外,如果集群长时间(比如数小时)内没有进行 SQL 查询,计算资源就会被回收,这样下次访问时就会变成冷访问。 -要避免这种尾部延迟,可在实际工作负载前使用类似的向量搜索查询对向量索引进行热身。 \ No newline at end of file +要避免这种查询延迟,可在实际工作负载前,使用类似的向量搜索查询对索引进行预热。 \ No newline at end of file diff --git a/vector-search-index.md b/vector-search-index.md index d73d44ff585c..20dcdfdf04e9 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -1,65 +1,66 @@ --- title: 向量搜索索引 -summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (KNN) 查询 +summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (KNN) 查询。 --- # 向量搜索索引 -K 近邻 (KNN) 搜索是在向量空间中找到距离给定向量最近的 K 个向量的查询。要找到最近的 K 个向量,最直接的方法就是暴力搜索,即计算向量空间中所有点与给定向量之间的距离。这种方法拥有最好的精确度,但在实际的搜索中,往往搜索速度太慢。因此,近邻搜索问题通常采用近似算法来解决。 +K 近邻(K-Nearest Neighbors,简称 KNN)搜索是一种在向量空间中找到距离给定向量最近的 K 个向量的查询。实现 K 近邻搜索最直接的方法是暴力搜索(即计算向量空间中所有点与给定向量之间的距离),这种方法可以达到最高的精确度,但在实际应用中其搜索速度往往过于缓慢。因此,K 近邻搜索通常会采用近似算法来提高搜索效率。 -在 TiDB 中,你可以创建并利用向量搜索索引来对 [向量类型](/vector-search-data-types.md) 的列进行近似近邻 (ANN) 搜索。通过使用向量搜索索引,整个查询可在几毫秒内完成。 +在 TiDB 中,你可以创建并利用向量搜索索引来对[向量数据类型](/vector-search-data-types.md)的列进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索。通过使用向量搜索索引,整个查询可在几毫秒内完成。 TiDB 目前支持以下向量搜索索引算法: - HNSW - ## 创建 HNSW 向量搜索索引 -[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是最流行的向量搜索索引算法。HNSW 索引的性能良好,且准确率相对较高 (特定情况下可达 98%), +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是当前最流行的向量搜索索引算法之一。它性能良好,而且准确率相对较高 (特定情况下可达 98%)。 -要创建 HNSW 向量搜索索引,你可以在创建表格时,使用以下语法指定为哪一列的[向量数据类型](/vector-search-data-types.md)构建索引: +在 TiDB 中,你可以通过以下任一种方式为[向量数据类型](/vector-search-data-types.md)的列创建 HNSW 索引。 -```sql -CREATE TABLE foo ( - id INT PRIMARY KEY, - data VECTOR(5), - data64 VECTOR64(10), - VECTOR INDEX data USING HNSW ((VEC_COSINE_DISTANCE(data))) -); -``` +- 在建表时,使用以下语法来指定为哪一个向量列创建 HNSW 索引: -如果已经创建了带有向量数据类型的表格,你可以通过 `ALTER TABLE` 的语法为向量数据创建索引,示例如下: + ```sql + CREATE TABLE foo ( + id INT PRIMARY KEY, + data VECTOR(5), + data64 VECTOR64(10), + VECTOR INDEX data USING HNSW ((VEC_COSINE_DISTANCE(data))) + ); + ``` -```sql -CREATE VECTOR INDEX idx_name USING HNSW ON foo ((VEC_COSINE_DISTANCE(data))) +- 对于现有的表,如果该表已包含向量列,通过 `ALTER TABLE` 语法为向量列创建 HNSW 索引: -ALTER TABLE foo ADD VECTOR INDEX idx_name USING HNSW ((VEC_COSINE_DISTANCE(data))) -``` + ```sql + CREATE VECTOR INDEX idx_name USING HNSW ON foo ((VEC_COSINE_DISTANCE(data))) + + ALTER TABLE foo ADD VECTOR INDEX idx_name USING HNSW ((VEC_COSINE_DISTANCE(data))) + ``` > **Note:** > -> 创建向量索引的语法可能在今后的版本中发生变化。 +> 创建向量索引目前为实验特性,其语法可能会在 GA 前发生变化。 -创建向量索引时,需要通过 `HNSW ((distance_metric(cols_name)))` 配置指定距离度量: +在创建 HNSW 向量索引时,你需要在 `HNSW ()` 中指定向量的距离函数: -- 余弦距离: `HNSW ((VEC_COSINE_DISTANCE(cols_name)))` -- L2 距离: `HNSW ((VEC_L2_DISTANCE(cols_name)))` +- 余弦距离:`HNSW ((VEC_COSINE_DISTANCE(cols_name)))` +- L2 距离:`HNSW ((VEC_L2_DISTANCE(cols_name)))` -只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引。它不能为混合维度的向量列 (如 `VECTOR` ) 创建,因为向量距离只能在具有相同维度的向量之间计算。 +你只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引,不能为混合维度的向量列 (如 `VECTOR` ) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 -如果你使用的是编程语言 SDK 或 ORM,请参阅以下文档以创建向量索引: +如果你使用的是编程语言 SDK 或 ORM,可以参阅以下文档创建向量索引: -- Python: [TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) -- Python: [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) -- Python: [Peewee](/vector-search-integrate-with-peewee.md) -- Python: [Django](/vector-search-integrate-with-django-orm.md) +- Python:[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) +- Python:[SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) +- Python:[Peewee](/vector-search-integrate-with-peewee.md) +- Python:[Django](/vector-search-integrate-with-django-orm.md) -有关向量搜索索引的相关约束和限制,请参阅 [向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束) +有关向量搜索索引的约束和限制,请参阅[向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束)。 ## 使用向量搜索索引 -在 K 近邻搜索查询中,可以使用 `ORDER BY ... LIMIT` 形式来使用向量搜索索引,如下所示: +在 K 近邻搜索查询中,可以通过 `ORDER BY ... LIMIT` 子句来使用向量搜索索引,如下所示: ```sql SELECT * @@ -68,14 +69,14 @@ ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') LIMIT 10 ``` -如果要在向量搜索中使用索引,则必须使用与创建向量索引时所定义的相同的距离度量。 +要在向量搜索中使用索引,请确保 `ORDER BY ... LIMIT` 子句中使用的距离函数与创建向量索引时 `HNSW ()` 中指定的距离函数相同。 -## 使用带过滤器的向量搜索索引 +## 使用带过滤条件的向量搜索索引 -包含预过滤 (使用 `WHERE` 子句) 的查询不能使用向量搜索索引,因为它们不是根据 SQL 语义查询的 K 近邻。例如 +包含预过滤条件 (使用 `WHERE` 子句) 的查询无法使用向量搜索索引,因为这样的查询并没有严格按照 SQL 语义来查询 K 近邻。 ```sql --- 过滤器在 kNN 之前执行,因此不能使用向量搜索索引: +-- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: SELECT * FROM vec_table WHERE category = "document" @@ -83,12 +84,12 @@ ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') LIMIT 5; ``` -以下是几种变通方法: +如需使用带过滤条件的向量搜索索引,可以采用以下几种方法: -**向量搜索后的后置过滤器:** 首先查询 K 个最近的邻居,然后过滤掉不需要的结果: +**向量搜索后再过滤:** 先查询 K 个最近的邻居,再过滤掉不需要的结果: ```sql --- 对于这些查询,过滤器是在 kNN 之后执行的,因此可以使用向量索引: +-- 对于以下查询,过滤条件是在 KNN 之后执行的,因此可以使用向量索引: SELECT * FROM ( @@ -101,19 +102,19 @@ WHERE category = "document"; -- 请注意,如果过滤掉一些结果,此查询返回的结果可能少于 5 个。 ``` -**使用表格分区**: [表分区](/partitioned-table.md)内的查询可以充分利用向量索引。如果要执行相等条件的过滤器,这将非常有效,因为相等条件的过滤器可以转化为访问指定分区。 +**对表进行分区**: 在[分区](/partitioned-table.md)内的查询可以充分利用向量索引。如果你需要进行等值过滤,这会非常有用,因为等值过滤可以转化为访问指定的分区。 -举例说明: 假设您想查找与特定产品版本最接近的文档。 +例如,假设你需要查找与特定产品版本最接近的文档: ```sql --- 过滤器在 kNN 之前执行,因此不能使用向量索引: +-- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: SELECT * FROM docs WHERE ver = "v2.0" ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') LIMIT 5; ``` -与其使用 `WHERE` 子句编写查询,不如对表进行分区,然后使用 [`PARTITION` 关键字](/partitioned-table.md#partition-selection) 在分区内进行查询: +如需使用向量搜索索引,你可以先对表进行分区,然后使用 [`PARTITION` 关键字](/partitioned-table.md#partition-selection) 在特定分区内进行查询,而不是使用 `WHERE` 子句。 ```sql CREATE TABLE docs ( @@ -134,11 +135,11 @@ ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') LIMIT 5; ``` -更多信息,请参阅 [表分区](/partitioned-table.md)。 +更多信息,请参阅[分区表](/partitioned-table.md)。 ## 查看索引构建进度 -与其他索引不同,向量搜索索引是异步建立的。因此,在批量数据插入后,向量索引可能无法立即使用。这不会影响数据的正确性或一致性,你可以随时执行向量搜索并获得完整的结果。不过,在向量搜索索引完全建立之前,性能将不会达到最佳。 +与其他索引不同,向量搜索索引是通过异步方式构建的。这意味着,在完成大批量数据插入后,向量索引可能不会立即构建完成以供查询使用,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 要查看索引构建进度,可以按如下方式查询 `INFORMATION_SCHEMA.TIFLASH_INDEXES` 表: @@ -152,13 +153,13 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; +---------------+------------+----------------+----------+--------------------+-------------+-----------+------------+---------------------+-------------------------+--------------------+------------------------+------------------+ ``` -- `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列显示索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,索引构建完成。 +- 可以通过 `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列查看索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,表示索引构建完成。 - 作为参考,500 MiB 的向量数据集构建索引的过程可能需要 20 分钟。索引构建器可以在多个表中并行构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 + 作为参考,对于一个 500 MiB 的向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 -- `ROWS_DELTA_NOT_INDEXED` 列显示 Delta 层中的行数。Delta 层存储 _最近_ 插入或更新的行,并根据写入工作量定期合并到稳定层。这个合并过程称为 “压缩”。 +- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到稳定层。这个合并过程称为“压缩”。 - Delta 层始终没有索引。为了达到最佳性能,可以强制将 Delta 层合并到稳定层,这样所有数据都能被索引: + Delta 层本身是不包含索引的。为了达到最佳性能,你可以强制将 Delta 层合并到稳定层,以确保所有的数据都能够被索引: ```sql ALTER TABLE COMPACT; @@ -166,11 +167,11 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 更多信息,请参阅 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md)。 -## 检查是否使用了向量搜索索引 +## 查看是否使用了向量搜索索引 -使用 [`EXPLAIN`](/sql-statements/sql-statement-explain.md) 或 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句检查该查询是否使用了向量搜索索引。当 `annIndex:` 出现在 `TableFullScan` 执行计划的 `operator info` 列中时,表示该表扫描使用了向量搜索索引。 +你可以使用 [`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 @@ -192,7 +193,7 @@ LIMIT 10; 9 rows in set (0.01 sec) ``` -**示例:由于未指定 Top K,因此未使用向量搜索索引** +**示例:由于未指定 Top K,导致未使用向量搜索索引的查询** ```sql [tidb]> EXPLAIN SELECT * FROM vector_table_with_index @@ -210,10 +211,10 @@ LIMIT 10; 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; @@ -221,7 +222,7 @@ 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; @@ -232,7 +233,7 @@ ANN index not used: index can be used only when ordering by vec_cosine_distance( ## 分析向量搜索性能 -[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句包含关于如何在 `execution info` 列中使用向量索引的详细信息: +你可以执行 [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) 语句,然后查看输出中的 `execution info` 列了解向量索引使用情况的详细信息: ```sql [tidb]> EXPLAIN ANALYZE SELECT * FROM vector_table_with_index @@ -258,30 +259,30 @@ LIMIT 10; > **Note:** > -> 执行信息为内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 +> 执行信息为 TiDB 内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 -一些重要字段的解释: +以下为一些重要字段的解释: -- `vector_index.load.total`: 加载索引的总持续时间。该字段可能大于实际查询时间,因为可能会并行加载多个向量索引。 -- `vector_index.load.from_s3`: 从 S3 加载的索引数量。 -- `vector_index.load.from_disk`: 从磁盘加载的索引数量。索引之前已从 S3 下载。 -- `vector_index.load.from_cache`: 从缓存中加载的索引数量。索引之前已从 S3 下载。 -- `vector_index.search.total`: 在索引中搜索的总持续时间。延迟大通常意味着索引是冷索引(以前从未被访问过,或很久以前被访问过),因此在索引中搜索时会产生大量 IO。这个字段可能大于实际查询时间,因为可能会并行搜索多个向量索引。 -- `vector_index.search.discarded_nodes`: 在搜索过程中已访问但被丢弃的向量行数。搜索结果不会考虑这些被丢弃的向量。如果数值较大,通常表示有很多由 UPDATE 或 DELETE 语句引起的陈旧行。 +- `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 Walkthrough](/explain-walkthrough.md) 来解释输出结果。 +关于执行信息输出的更多信息,请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [使用 `EXPLAIN` 解读执行计划](/explain-walkthrough.md)。 -## 向量搜索索引的约束 +## 使用限制 -- TiDB 集群需要创建 TiFlash 的副本 -- 不能是主键索引 -- 不能是复合索引 -- 不可以为同一列创建多个向量索引 -- 向量索引需要指定距离函数(目前只支持 `余弦距离` 和 `L2 距离`) -- 不支持删除具有向量索引的列,也不支持同时创建多个索引。 -- 不支持对向量索引设置 `invisible` 操作。 +- 集群需要提前部署 TiFlash 并为表创建 TiFlash 副本。 +- 向量搜索索引不能作为主键索引。 +- 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 +- 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 +- 不支持在同一列上创建多个向量搜索索引。 +- 不支持删除具有向量搜索索引的列,也不支持同时创建多个索引。 +- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 -## See also +## 另请参阅 - [优化向量搜索性能](/vector-search-improve-performance.md) - [向量数据类型](/vector-search-data-types.md) \ No newline at end of file From a250dff400cfb6f30368819b9d44119a143bc348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Sat, 14 Sep 2024 10:38:26 +0800 Subject: [PATCH 042/109] add vector index part in other document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 9 +++++++-- vector-search-integrate-with-django-orm.md | 19 ++++++++++++++++++- vector-search-integrate-with-peewee.md | 19 ++++++++++++++++++- vector-search-integrate-with-sqlalchemy.md | 14 ++++++++++++++ vector-search-limitations.md | 1 + 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 146fa67db45d..97aab2c602e8 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -14,6 +14,7 @@ summary: 本文介绍 TiDB 的向量数据类型。 与使用 [`JSON`](/data-type-json.md) 类型相比,使用向量类型具有以下优势: +- 支持向量索引。 可以通过构建[向量搜索索引](/vector-search-index.md)加速查询。 - 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。 - 存储格式更优。向量数据类型针对向量数据进行了特别优化,在空间利用和性能效率上都优于 `JSON` 类型。 @@ -52,7 +53,8 @@ ERROR 1105 (HY000): Invalid vector text: [5, ] ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3) ``` -可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 +可参阅 [向量函数与操作符](/vector-search-functions-and-operators.md) 了解向量数据类型支持的所有函数和操作符。 +可参阅 [向量搜索索引](/vector-search-index.md) 了解向量搜索索引的信息。 ## 混合存储不同维度的向量 @@ -68,6 +70,8 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 dimensions vector, INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK ``` +但是,我们不能为存储了不同维度的向量列构建 [向量搜索索引](/vector-search-index.md),因为向量距离只能在具有相同维度的向量之间计算。 + ## 比较 [比较运算符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符)了解向量数据类型支持的所有函数和操作符。 @@ -239,4 +243,5 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 另请参阅 -- [向量函数和操作符](/vector-search-functions-and-operators.md) \ No newline at end of file +- [向量函数和操作符](/vector-search-functions-and-operators.md) +- [向量搜索索引](/vector-search-index.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 index 9c7ce2f86691..c279a9bef2d0 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -224,6 +224,22 @@ Document.objects.create(content="fish", embedding=[1, 2, 4]) Document.objects.create(content="tree", embedding=[1, 0, 0]) ``` +#### 用索引定义优化的向量列 + +定义三维向量列,并使用 [向量搜索索引 (HNSW 索引)](/vector-search-index.md) 对其进行优化。 + +```python +class DocumentWithIndex(models.Model): + content = models.TextField() + # Note: + # - Using comment to add hnsw index is a temporary solution. In the future it will use `CREATE INDEX` syntax. + # - Currently the HNSW index cannot be changed after the table has been created. + # - Only Django >= 4.2 supports `db_comment`. + embedding = VectorField(dimensions=3, db_comment="VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") +``` + +TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 + ### 搜索近邻向量 TiDB 向量支持以下距离函数: @@ -253,4 +269,5 @@ results = Document.objects.annotate( ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/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 index d06e1e52f38d..3a3fc3d23d5e 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -223,6 +223,22 @@ Document.create(content='fish', embedding=[1, 2, 4]) Document.create(content='tree', embedding=[1, 0, 0]) ``` +#### 用索引定义优化的向量列 + +定义三维矢量列,并使用 [向量搜索索引](/vector-search-index.md) (HNSW 索引) 对其进行优化。 + +```python +class DocumentWithIndex(Model): + class Meta: + database = db + table_name = 'peewee_demo_documents_with_index' + + content = TextField() + embedding = VectorField(3, constraints=[SQL("VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))")]) +``` + +TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 + ### 搜索近邻向量 可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 @@ -244,4 +260,5 @@ results = Document.select(Document, distance).where(distance_expression < 0.2).o ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/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 index 5650b5bb2cb5..6094302d28e1 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -186,6 +186,20 @@ with Session(engine) as session: session.commit() ``` +#### 用索引定义优化的矢量列 + +定义三维矢量列,并使用 [向量量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 + +```python +class DocumentWithIndex(Base): + __tablename__ = 'sqlalchemy_demo_documents_with_index' + id = Column(Integer, primary_key=True) + content = Column(Text) + embedding = Column(VectorType(3), comment="VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") +``` + +TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 + ### 搜索近邻向量 可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 5c0af31dc65e..838cf8216687 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -9,6 +9,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 创建 [向量搜索索引](/vector-search-index.md) 时只支持余弦距离和L2距离。 - 目前,向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量字段插入或存储数据时,如果这些数据的类型是双精度浮点数,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 ## 反馈 From 634c602580107c14eca2c63c6124e3bff8403eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Sat, 14 Sep 2024 10:44:03 +0800 Subject: [PATCH 043/109] modify index name when create vector index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 4 ++-- vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-peewee.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 51c11ed96922..b250805af730 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -26,7 +26,7 @@ TiDB 目前支持以下向量搜索索引算法: id INT PRIMARY KEY, data VECTOR(5), data64 VECTOR64(10), - VECTOR INDEX data USING HNSW ((VEC_COSINE_DISTANCE(data))) + VECTOR INDEX idx_data USING HNSW ((VEC_COSINE_DISTANCE(data))) ); ``` @@ -122,7 +122,7 @@ CREATE TABLE docs ( ver VARCHAR(10), doc TEXT, embedding VECTOR(3), - VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding))) + 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'), diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index c279a9bef2d0..02a8ac58d029 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -235,7 +235,7 @@ class DocumentWithIndex(models.Model): # - Using comment to add hnsw index is a temporary solution. In the future it will use `CREATE INDEX` syntax. # - Currently the HNSW index cannot be changed after the table has been created. # - Only Django >= 4.2 supports `db_comment`. - embedding = VectorField(dimensions=3, db_comment="VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") + embedding = VectorField(dimensions=3, db_comment="VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") ``` TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 3a3fc3d23d5e..611277c0d0b9 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -234,7 +234,7 @@ class DocumentWithIndex(Model): table_name = 'peewee_demo_documents_with_index' content = TextField() - embedding = VectorField(3, constraints=[SQL("VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))")]) + embedding = VectorField(3, constraints=[SQL("VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))")]) ``` TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 6094302d28e1..484e52b62292 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -195,7 +195,7 @@ class DocumentWithIndex(Base): __tablename__ = 'sqlalchemy_demo_documents_with_index' id = Column(Integer, primary_key=True) content = Column(Text) - embedding = Column(VectorType(3), comment="VECTOR INDEX embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") + embedding = Column(VectorType(3), comment="VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") ``` TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 From 4b54e6dd86390494d44627e6006ce63d9aa76059 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Sat, 14 Sep 2024 11:04:20 +0800 Subject: [PATCH 044/109] Update vector-search-improve-performance.md --- vector-search-improve-performance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 6c9cc96a171b..6928a79f7ae6 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -17,7 +17,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 减少向量维数或缩短嵌入时间 -随着向量大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 +随着向量维度大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,你需要确保改变嵌入模型对向量查询准确性的影响。 From 5eeb3363b0a41e5aaeca92d7d58bc7a6f5d2b657 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Sat, 14 Sep 2024 12:12:12 +0800 Subject: [PATCH 045/109] refine descriptions for TiDB self-managed connection --- vector-search-get-started-using-python.md | 25 ++++++------- vector-search-integrate-with-django-orm.md | 25 ++++++------- ...-search-integrate-with-jinaai-embedding.md | 36 +++++++++---------- vector-search-integrate-with-langchain.md | 18 ++++++---- vector-search-integrate-with-llamaindex.md | 16 ++++++--- vector-search-integrate-with-peewee.md | 20 +++++------ vector-search-integrate-with-sqlalchemy.md | 16 +++++---- 7 files changed, 86 insertions(+), 70 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 4995de2278bd..b21292984ce2 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -49,13 +49,22 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv ### 第 3 步:配置 TiDB 集群的连接字符串 -根据不同的 TiDB 集群部署方式,配置集群的连接字符串 +根据不同的 TiDB 集群部署方式,配置集群的连接字符串。
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量,将连接字符串复制到 `.env` 文件中。以下是各个变量的含义: +对于本地部署的 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 集群的端口。 @@ -63,20 +72,12 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv - ``:连接 TiDB 集群的密码。 - ``:要连接的数据库名称。 -以下为 MacOS 的示例: - -```dotenv -# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" -TIDB_DATABASE_URL="mysql+pymysql://:@:/" -``` -> **Tip:** -> -> `` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 -
+对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 9c7ce2f86691..71cd26e57663 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -74,15 +74,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv
-在 Python 项目的根目录下新建一个 `.env` 文件,并根据集群的启动参数修改相应的环境变量。 - -- `TIDB_HOST`:TiDB 集群的主机号。 -- `TIDB_PORT`:TiDB 集群的端口号。 -- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 -- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 -- `TIDB_DATABASE`:要连接的数据库名称。 - -以下为 MacOS 的示例: +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: ```dotenv TIDB_HOST=127.0.0.1 @@ -91,14 +83,23 @@ TIDB_USERNAME=root TIDB_PASSWORD= TIDB_DATABASE=test ``` -> **Tip:** -> -> `TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 + +如果你在本机运行 TiDB,`TIDB_HOST` 默认为 `127.0.0.1`。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- `TIDB_HOST`:TiDB 集群的主机号。 +- `TIDB_PORT`:TiDB 集群的端口号。 +- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 +- `TIDB_DATABASE`:要连接的数据库名称。
+对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index d51fe467aa8a..2e07fb966870 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -62,30 +62,30 @@ pip install -r requirements.txt
-你可以通过在终端中直接设置环境变量以连接 TiDB 集群: - - ```shell - export JINA_API_KEY="****" - # 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" - export TIDB_DATABASE_URL="mysql+pymysql://:@:/" - ``` - - 注意替换参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 Host 地址为 `127.0.0.1`,密码为空。以下是各个参数的解释: - - - `HOST`:TiDB 集群的主机号。 - - `PORT`:TiDB 集群的端口号。 - - `USERNAME`:连接 TiDB 集群的用户名。 - - `PASSWORD`:连接 TiDB 集群的密码。 - - `DATABASE`:要连接的数据库名称。 -> **Tip:** -> -> `PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 +对于本地部署的 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,`TIDB_HOST` 默认为 `127.0.0.1`。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- `HOST`:TiDB 集群的主机地址。 +- `PORT`:TiDB 集群的端口号。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。
+对于 TiDB Serverless 集群,请按照以下步骤配置 TiDB 连接参数: + 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index c103eca4102a..542d56b9fdaa 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -63,7 +63,7 @@ from langchain_text_splitters import CharacterTextSplitter
-本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供从集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 +本文档使用 [OpenAI](https://platform.openai.com/docs/introduction) 作为嵌入模型生成向量嵌入。在此步骤中,你需要提供集群的连接字符串和 [OpenAI API 密钥](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key)。 运行以下代码,配置环境变量。代码运行后,系统会提示输入连接字符串和 OpenAI API 密钥: @@ -78,24 +78,28 @@ tidb_connection_string = getpass.getpass("TiDB Connection String:") os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") ``` -例如,macOS 上的连接字符串如下所示: +以 macOS 为例,集群的连接字符串如下所示: ```dotenv -# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如:TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" ``` -> **Tip:** -> -> 注意替换为你的 TiDB 实际对应的值。`PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 +请替换连接字符串中的参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 `HOST` 地址为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 +以下为各参数的解释: +- `HOST`:TiDB 集群的主机地址。 +- `PORT`:TiDB 集群的端口号。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。
-对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 群集的连接字符串,然后配置环境变量: +对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index ecdc1be6f667..a69478da3745 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -77,20 +77,28 @@ tidb_connection_string = getpass.getpass("TiDB Connection String:") os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:") ``` -例如,macOS 上的连接字符串如下所示: +以 macOS 为例,集群的连接字符串如下所示: ```dotenv -# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" TIDB_DATABASE_URL="mysql+pymysql://:@:/" +# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" ``` -注意替换为你的 TiDB 实际对应的值。`PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 +请替换连接字符串中的参数为你的 TiDB 实际对应的值。如果你在本机运行 TiDB,默认 `HOST` 地址为 `127.0.0.1`。`PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- `HOST`:TiDB 集群的主机地址。 +- `PORT`:TiDB 集群的端口号。 +- `USERNAME`:连接 TiDB 集群的用户名。 +- `PASSWORD`:连接 TiDB 集群的密码。 +- `DATABASE`:要连接的数据库名称。
-对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 群集的连接字符串,然后配置环境变量: +对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 集群的连接字符串,然后配置环境变量: 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index d06e1e52f38d..a296b9c76452 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -64,9 +64,9 @@ pip install peewee pymysql python-dotenv tidb-vector
-在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制进 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: -```shell +```dotenv TIDB_HOST=127.0.0.1 TIDB_PORT=4000 TIDB_USERNAME=root @@ -74,21 +74,21 @@ TIDB_PASSWORD= TIDB_DATABASE=test ``` -- `TIDB_HOST`: TiDB 集群的主机号。 -- `TIDB_PORT`: TiDB 集群的端口号。 -- `TIDB_USERNAME`: 连接 TiDB 集群的用户名。 -- `TIDB_PASSWORD`: 连接 TiDB 集群的密码。 -- `TIDB_DATABASE`: 要连接的数据库名称。 +如果你在本机运行 TiDB,`TIDB_HOST` 默认为 `127.0.0.1`。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 +以下为各参数的解释: -> **Tip:** -> -> 注意替换为你的 TiDB 实际对应的值。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 +- `TIDB_HOST`:TiDB 集群的主机号。 +- `TIDB_PORT`:TiDB 集群的端口号。 +- `TIDB_USERNAME`:连接 TiDB 集群的用户名。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。集群初始密码为空,第一次启动集群时无需带上此字段。 +- `TIDB_DATABASE`:要连接的数据库名称。
+对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 5650b5bb2cb5..afe60a21fb09 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -64,27 +64,29 @@ pip install pymysql python-dotenv sqlalchemy tidb-vector
-在 Python 项目的根目录下新建一个 `.env` 文件,将一下内容复制到 `.env` 文件中,并根据集群的启动参数修改相应的环境变量。 +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: -```shell -# 例如: TIDB_DATABASE_URL="mysql+pymysql://root@127.0.0.1:4000/test" +```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 集群的密码。 - ``:要连接的数据库名称。 -> **Tip:** -> -> 注意替换为你的 TiDB 实际对应的值。`TIDB_PASSWORD` 初始密码为空,若你是第一次启动集群,则不需要带上此字段。 -
+对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: + 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 From 9a77c658b92d6586b65143c6db8cd264e81229d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Sat, 14 Sep 2024 13:38:05 +0800 Subject: [PATCH 046/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index b250805af730..810f0fd9dd2e 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -30,22 +30,22 @@ TiDB 目前支持以下向量搜索索引算法: ); ``` -- 对于现有的表,如果该表已包含向量列,通过 `ALTER TABLE` 语法为向量列创建 HNSW 索引: +- 对于现有的表,如果该表已包含向量列,可以通过以下语法为向量列创建 HNSW 索引: ```sql - CREATE VECTOR INDEX idx_name USING HNSW ON foo ((VEC_COSINE_DISTANCE(data))) + CREATE VECTOR INDEX idx_name ON foo ((VEC_COSINE_DISTANCE(data))) USING HNSW; - ALTER TABLE foo ADD VECTOR INDEX idx_name USING HNSW ((VEC_COSINE_DISTANCE(data))) + ALTER TABLE foo ADD VECTOR INDEX idx_name ((VEC_COSINE_DISTANCE(data))) USING HNSW; ``` > **Note:** > > 创建向量索引目前为实验特性,其语法可能会在 GA 前发生变化。 -在创建 HNSW 向量索引时,你需要在 `HNSW ()` 中指定向量的距离函数: +在创建 HNSW 向量索引时,你需要指定向量的距离函数: -- 余弦距离:`HNSW ((VEC_COSINE_DISTANCE(cols_name)))` -- L2 距离:`HNSW ((VEC_L2_DISTANCE(cols_name)))` +- 余弦距离:`((VEC_COSINE_DISTANCE(cols_name))) USING HNSW` +- L2 距离:`((VEC_L2_DISTANCE(cols_name))) USING HNSW` 你只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引,不能为混合维度的向量列 (如 `VECTOR` ) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 @@ -168,6 +168,8 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 更多信息,请参阅 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md)。 +同时,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 `DDL job` 执行进度,观察其 `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 在扫描该表时使用了向量搜索索引。 @@ -276,7 +278,7 @@ LIMIT 10; ## 使用限制 - 集群需要提前部署 TiFlash 并为表创建 TiFlash 副本。 -- 向量搜索索引不能作为主键索引。 +- 向量搜索索引不能作为主键或者唯一索引。 - 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 - 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 From 502bd52f56320dc04acf4916ed26d54e93a301a6 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Sat, 14 Sep 2024 14:15:05 +0800 Subject: [PATCH 047/109] vector-index: refine descriptions --- vector-search-data-types.md | 9 +++++---- vector-search-integrate-with-django-orm.md | 4 ++-- vector-search-integrate-with-peewee.md | 4 ++-- vector-search-integrate-with-sqlalchemy.md | 6 +++--- vector-search-limitations.md | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 97aab2c602e8..7c40cfaa7fa9 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -14,7 +14,7 @@ summary: 本文介绍 TiDB 的向量数据类型。 与使用 [`JSON`](/data-type-json.md) 类型相比,使用向量类型具有以下优势: -- 支持向量索引。 可以通过构建[向量搜索索引](/vector-search-index.md)加速查询。 +- 支持向量索引。可以通过构建[向量搜索索引](/vector-search-index.md)加速查询。 - 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。 - 存储格式更优。向量数据类型针对向量数据进行了特别优化,在空间利用和性能效率上都优于 `JSON` 类型。 @@ -53,8 +53,9 @@ ERROR 1105 (HY000): Invalid vector text: [5, ] ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3) ``` -可参阅 [向量函数与操作符](/vector-search-functions-and-operators.md) 了解向量数据类型支持的所有函数和操作符。 -可参阅 [向量搜索索引](/vector-search-index.md) 了解向量搜索索引的信息。 +可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)了解向量数据类型支持的所有函数和操作符。 + +可参阅[向量搜索索引](/vector-search-index.md)了解向量搜索索引的信息。 ## 混合存储不同维度的向量 @@ -70,7 +71,7 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 dimensions vector, INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK ``` -但是,我们不能为存储了不同维度的向量列构建 [向量搜索索引](/vector-search-index.md),因为向量距离只能在具有相同维度的向量之间计算。 +需要注意的是,存储了不同维度向量的列不支持构建[向量搜索索引](/vector-search-index.md),因为只有维度相同的向量之间才能计算向量距离。 ## 比较 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index adb64ec76275..b06dbde85cad 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -225,9 +225,9 @@ Document.objects.create(content="fish", embedding=[1, 2, 4]) Document.objects.create(content="tree", embedding=[1, 0, 0]) ``` -#### 用索引定义优化的向量列 +#### 定义带索引优化的向量列 -定义三维向量列,并使用 [向量搜索索引 (HNSW 索引)](/vector-search-index.md) 对其进行优化。 +定义一个三维向量列,并使用[向量搜索索引](/vector-search-index.md)(HNSW 索引)对其进行优化。 ```python class DocumentWithIndex(models.Model): diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 5f025c8e4851..76d8ef1bc091 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -223,9 +223,9 @@ Document.create(content='fish', embedding=[1, 2, 4]) Document.create(content='tree', embedding=[1, 0, 0]) ``` -#### 用索引定义优化的向量列 +#### 定义带索引优化的向量列 -定义三维矢量列,并使用 [向量搜索索引](/vector-search-index.md) (HNSW 索引) 对其进行优化。 +定义一个三维向量列,并使用[向量搜索索引](/vector-search-index.md)(HNSW 索引)对其进行优化。 ```python class DocumentWithIndex(Model): diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index a3028d569b56..532d494cbd7c 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -188,9 +188,9 @@ with Session(engine) as session: session.commit() ``` -#### 用索引定义优化的矢量列 +#### 定义带索引优化的向量列 -定义三维矢量列,并使用 [向量量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 +定义一个三维向量列,并使用[向量搜索索引](/vector-search-index.md)(HNSW 索引)对其进行优化。 ```python class DocumentWithIndex(Base): @@ -200,7 +200,7 @@ class DocumentWithIndex(Base): embedding = Column(VectorType(3), comment="VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") ``` -TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 +TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 ### 搜索近邻向量 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 838cf8216687..43a905d2ab10 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -9,7 +9,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 创建 [向量搜索索引](/vector-search-index.md) 时只支持余弦距离和L2距离。 +- 创建[向量搜索索引](/vector-search-index.md)时,只支持余弦距离和 L2 距离 (欧氏距离)这两种距离度量方法。 - 目前,向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量字段插入或存储数据时,如果这些数据的类型是双精度浮点数,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 ## 反馈 From 652b639bf349a74b7f8e5f70c21f66d84252b488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Sat, 14 Sep 2024 14:46:19 +0800 Subject: [PATCH 048/109] remove index part when create table in integration-doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-integrate-with-django-orm.md | 16 ---------------- ...or-search-integrate-with-jinaai-embedding.md | 7 ++++--- vector-search-integrate-with-langchain.md | 3 ++- vector-search-integrate-with-llamaindex.md | 3 ++- vector-search-integrate-with-peewee.md | 16 ---------------- vector-search-integrate-with-sqlalchemy.md | 17 ++--------------- 6 files changed, 10 insertions(+), 52 deletions(-) diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index adb64ec76275..69727a10d0d9 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -225,22 +225,6 @@ Document.objects.create(content="fish", embedding=[1, 2, 4]) Document.objects.create(content="tree", embedding=[1, 0, 0]) ``` -#### 用索引定义优化的向量列 - -定义三维向量列,并使用 [向量搜索索引 (HNSW 索引)](/vector-search-index.md) 对其进行优化。 - -```python -class DocumentWithIndex(models.Model): - content = models.TextField() - # Note: - # - Using comment to add hnsw index is a temporary solution. In the future it will use `CREATE INDEX` syntax. - # - Currently the HNSW index cannot be changed after the table has been created. - # - Only Django >= 4.2 supports `db_comment`. - embedding = VectorField(dimensions=3, db_comment="VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") -``` - -TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 - ### 搜索近邻向量 TiDB 向量支持以下距离函数: diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 2e07fb966870..56d4bfc9aa28 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -210,8 +210,8 @@ class Document(Base): 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), - comment="hnsw(distance=cosine)" + VectorType(dim=768) + ) ``` > **Note:** @@ -272,4 +272,5 @@ with Session(engine) as session: ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/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 index 542d56b9fdaa..5131472b67ff 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -627,4 +627,5 @@ vector_store.tidb_vector_client.execute("DROP TABLE airplan_routes") ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/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 index a69478da3745..8868cb76094f 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -307,4 +307,5 @@ Empty Response ## 另请参阅 -- [向量数据类型](/tidb-cloud/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/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 index 5f025c8e4851..b17ecab0cf96 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -223,22 +223,6 @@ Document.create(content='fish', embedding=[1, 2, 4]) Document.create(content='tree', embedding=[1, 0, 0]) ``` -#### 用索引定义优化的向量列 - -定义三维矢量列,并使用 [向量搜索索引](/vector-search-index.md) (HNSW 索引) 对其进行优化。 - -```python -class DocumentWithIndex(Model): - class Meta: - database = db - table_name = 'peewee_demo_documents_with_index' - - content = TextField() - embedding = VectorField(3, constraints=[SQL("VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))")]) -``` - -TiDB 将使用该索引来加速基于余弦距离函数的向量搜索查询。 - ### 搜索近邻向量 可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index a3028d569b56..15e501ad1bde 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -188,20 +188,6 @@ with Session(engine) as session: session.commit() ``` -#### 用索引定义优化的矢量列 - -定义三维矢量列,并使用 [向量量搜索索引](/vector-search-index.md) (HNSW 索引)对其进行优化。 - -```python -class DocumentWithIndex(Base): - __tablename__ = 'sqlalchemy_demo_documents_with_index' - id = Column(Integer, primary_key=True) - content = Column(Text) - embedding = Column(VectorType(3), comment="VECTOR INDEX idx_embedding USING HNSW ((VEC_COSINE_DISTANCE(embedding)))") -``` - -TiDB 将使用该索引来加速基于余弦距离函数的矢量搜索查询。 - ### 搜索近邻向量 可以选择使用余弦距离 (`CosineDistance`) 函数,查询与向量 `[1, 2, 3]` 语义最接近的前 3 个 `document`。 @@ -228,4 +214,5 @@ with Session(engine) as session: ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file From cfacbef68ceb7b57ad46662317120ae1e99facac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Sat, 14 Sep 2024 15:01:44 +0800 Subject: [PATCH 049/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 810f0fd9dd2e..2c9fe5bfd661 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -49,13 +49,6 @@ TiDB 目前支持以下向量搜索索引算法: 你只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引,不能为混合维度的向量列 (如 `VECTOR` ) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 -如果你使用的是编程语言 SDK 或 ORM,可以参阅以下文档创建向量索引: - -- Python:[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) -- Python:[SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) -- Python:[Peewee](/vector-search-integrate-with-peewee.md) -- Python:[Django](/vector-search-integrate-with-django-orm.md) - 有关向量搜索索引的约束和限制,请参阅[向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束)。 ## 使用向量搜索索引 From eb42ae86cb30f1616211cda8e17c3de6016e1910 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Sat, 14 Sep 2024 16:14:45 +0800 Subject: [PATCH 050/109] TiDB Serverless -> TiDB Cloud Serverless --- vector-search-get-started-using-python.md | 8 ++++---- vector-search-get-started-using-sql.md | 6 +++--- vector-search-integrate-with-django-orm.md | 10 +++++----- vector-search-integrate-with-jinaai-embedding.md | 8 ++++---- vector-search-integrate-with-langchain.md | 8 ++++---- vector-search-integrate-with-llamaindex.md | 8 ++++---- vector-search-integrate-with-peewee.md | 8 ++++---- vector-search-integrate-with-sqlalchemy.md | 8 ++++---- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index b21292984ce2..f77791a1adf6 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -20,7 +20,7 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -74,11 +74,11 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/"
-
+
-对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index 7a684d50e168..f306c3425eda 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -24,7 +24,7 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -46,9 +46,9 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md)
-
+
-1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 69727a10d0d9..49bd51d2d448 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -18,7 +18,7 @@ summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 @@ -72,7 +72,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv -
+
对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: @@ -96,11 +96,11 @@ TIDB_DATABASE=test
-
+
-对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 56d4bfc9aa28..50771c814bfe 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -18,7 +18,7 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 @@ -82,11 +82,11 @@ export TIDB_DATABASE_URL="mysql+pymysql://:@:/ -
+
-对于 TiDB Serverless 集群,请按照以下步骤配置 TiDB 连接参数: +对于 TiDB Cloud Serverless 集群,请按照以下步骤配置 TiDB 连接参数: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index 5131472b67ff..bfbccd15e9d8 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -23,7 +23,7 @@ summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -97,11 +97,11 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/ -
+
-对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 8868cb76094f..e338f755d0ce 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -23,7 +23,7 @@ summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 @@ -96,11 +96,11 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/ -
+
-对于 TiDB Serverless 集群,请按照以下步骤获取 TiDB 集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取 TiDB 集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index b17ecab0cf96..2b3cd1270f4e 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -18,7 +18,7 @@ summary: 了解如何在 peewee 中通过 TiDB 向量搜索功能存储向量并 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 @@ -86,11 +86,11 @@ TIDB_DATABASE=test
-
+
-对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 15e501ad1bde..ff8b428fd05c 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -18,7 +18,7 @@ summary: 了解如何在 SQLAlchemy 中通过 TiDB 向量搜索功能存储向 如果你还没有 TiDB 集群,可以按照以下任一种方式创建: - 参考[部署本地测试 TiDB 集群](/quick-start-with-tidb.md#部署本地测试集群)或[部署正式 TiDB 集群](/production-deployment-using-tiup.md),创建本地集群。 -- 参考[创建 TiDB Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 +- 参考[创建 TiDB Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 @@ -83,11 +83,11 @@ TIDB_DATABASE_URL=mysql+pymysql://:@:/
-
+
-对于 TiDB Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: +对于 TiDB Cloud Serverless 集群,请按照以下步骤获取集群的连接字符串,然后配置环境变量: -1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Serverless 集群名,进入集群的 **Overview** 页面。 +1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 From 8d938d4c71402024179f5f89a712fe5673c737d0 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 18 Sep 2024 18:20:58 +0800 Subject: [PATCH 051/109] add the experimental warning --- vector-search-data-types.md | 4 ++++ vector-search-functions-and-operators.md | 4 ++++ vector-search-get-started-using-python.md | 4 ++++ vector-search-get-started-using-sql.md | 4 ++++ vector-search-improve-performance.md | 4 ++++ vector-search-index.md | 4 ++++ vector-search-integrate-with-django-orm.md | 4 ++++ vector-search-integrate-with-jinaai-embedding.md | 4 ++++ vector-search-integrate-with-langchain.md | 4 ++++ vector-search-integrate-with-llamaindex.md | 4 ++++ vector-search-integrate-with-peewee.md | 4 ++++ vector-search-integrate-with-sqlalchemy.md | 4 ++++ vector-search-integration-overview.md | 4 ++++ vector-search-limitations.md | 4 ++++ vector-search-overview.md | 4 ++++ 15 files changed, 60 insertions(+) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 7c40cfaa7fa9..75c6be9226db 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -7,6 +7,10 @@ summary: 本文介绍 TiDB 的向量数据类型。 向量指的是一组浮点数序列,例如 `[0.3, 0.5, -0.1, ...]`。针对 AI 应用中大量使用到的嵌入向量 (vector embedding) 数据,TiDB 专门提供了向量数据类型,以便高效地存储和访问这些数据。 +> **警告:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + 目前支持的向量数据类型包括: - `VECTOR`: 存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。 diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 33c6a37f1eff..7d6865100f08 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -7,6 +7,10 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 本文介绍 TiDB 支持的向量函数和操作符。 +> **警告:** +> +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 向量函数 TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量函数: diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index f77791a1adf6..63b7e80f043d 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -9,6 +9,10 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 在本文中,你将使用 [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) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index f306c3425eda..f3eccebe547b 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -14,6 +14,10 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) - 存储向量嵌入 - 执行向量搜索查询 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 6928a79f7ae6..979ce78bbb6c 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -7,6 +7,10 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 在 TiDB 中,你可以通过向量搜索功能进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索,查找与给定的图像、文档等相似的结果。为了提升查询性能,请参考以下最佳实践。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 为向量列添加向量搜索索引 [向量搜索索引](/vector-search-index.md)可显著提高向量搜索查询的性能,通常能提高 10 倍或更多,而召回率仅略有下降。 diff --git a/vector-search-index.md b/vector-search-index.md index 2c9fe5bfd661..ff9b07b95f63 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -9,6 +9,10 @@ K 近邻(K-Nearest Neighbors,简称 KNN)搜索是一种在向量空间中 在 TiDB 中,你可以创建并利用向量搜索索引来对[向量数据类型](/vector-search-data-types.md)的列进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索。通过使用向量搜索索引,整个查询可在几毫秒内完成。 +> **警告:** +> +> 向量搜索索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + TiDB 目前支持以下向量搜索索引算法: - HNSW diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 49bd51d2d448..2966271e65fd 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -7,6 +7,10 @@ summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向 本文档将展示如何使用 [Django](https://www.djangoproject.com/) ORM 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 50771c814bfe..d251879e493a 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -7,6 +7,10 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, 本文档将展示如何使用 [Jina AI](https://jina.ai/) 为文本数据生成向量嵌入,然后将向量嵌入存储在 TiDB 中,并根据向量嵌入搜索相似文本。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index bfbccd15e9d8..7025a7ca072e 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -7,6 +7,10 @@ summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 本文档将展示如何在 [LangChain](https://python.langchain.com/) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + > **Note** > > 你可以在 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) 在线环境中运行示例代码。 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index e338f755d0ce..5c319715681e 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -7,6 +7,10 @@ summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 本文档将展示如何在 [LlamaIndex](https://www.llamaindex.ai) 中使用 [TiDB 向量搜索](/vector-search-overview.md)。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + > **Note** > > 你可以在 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) 在线环境中运行示例代码。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 2b3cd1270f4e..a1d6974a972b 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -7,6 +7,10 @@ summary: 了解如何在 peewee 中通过 TiDB 向量搜索功能存储向量并 本文档将展示如何使用 [peewee](https://docs.peewee-orm.com/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index ff8b428fd05c..8c5108e09dbc 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -7,6 +7,10 @@ summary: 了解如何在 SQLAlchemy 中通过 TiDB 向量搜索功能存储向 本文档将展示如何使用 [SQLAlchemy](https://www.sqlalchemy.org/) 与 [TiDB 向量搜索](/vector-search-overview.md)进行交互,以及如何存储向量和执行向量搜索查询。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 前置需求 为了能够顺利完成本文中的操作,你需要提前: diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index f561778e8356..d02a4b0cf6ab 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -7,6 +7,10 @@ summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库 本文档介绍了 TiDB 向量搜索支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## AI 框架 TiDB 目前支持以下 AI 框架。在这些 AI 框架下,你可以使用 TiDB 向量搜索构建 AI 应用程序。 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 43a905d2ab10..21e21631926e 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -7,6 +7,10 @@ summary: 了解 TiDB 向量搜索功能的限制。 本文档介绍 TiDB 向量搜索的已知限制。在未来的版本中,我们会持续新增更多功能来提升使用体验。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 - 创建[向量搜索索引](/vector-search-index.md)时,只支持余弦距离和 L2 距离 (欧氏距离)这两种距离度量方法。 diff --git a/vector-search-overview.md b/vector-search-overview.md index 58415a631b6e..30b1827ec4f6 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -7,6 +7,10 @@ summary: 介绍 TiDB 向量搜索功能。TiDB 向量搜索可以对文档、图 TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、图像、音频和视频等多种数据类型之间进行相似度搜索。TiDB 向量搜索的 SQL 语法与 MySQL 兼容,熟悉 MySQL 的开发人员可以基于该功能轻松构建人工智能 (AI) 应用。 +> **警告:** +> +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 + ## 概念 向量搜索是一种优先考虑数据语义以提供相关结果的搜索方法。 From f7a31f267d510a94738688e44af42660374fa2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 19 Sep 2024 09:48:10 +0800 Subject: [PATCH 052/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index ff9b07b95f63..335165b1cc57 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -17,6 +17,16 @@ TiDB 目前支持以下向量搜索索引算法: - HNSW +## 使用限制 + +- 集群需要提前部署 TiFlash 节点。 +- 向量搜索索引不能作为主键或者唯一索引。 +- 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 +- 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 +- 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 +- 不支持删除具有向量搜索索引的列,也不支持同时创建多个索引。 +- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 + ## 创建 HNSW 向量搜索索引 [HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是当前最流行的向量搜索索引算法之一。它性能良好,而且准确率相对较高 (特定情况下可达 98%)。 @@ -272,16 +282,6 @@ LIMIT 10; 关于执行信息输出的更多信息,请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及 [使用 `EXPLAIN` 解读执行计划](/explain-walkthrough.md)。 -## 使用限制 - -- 集群需要提前部署 TiFlash 并为表创建 TiFlash 副本。 -- 向量搜索索引不能作为主键或者唯一索引。 -- 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 -- 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 -- 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 -- 不支持删除具有向量搜索索引的列,也不支持同时创建多个索引。 -- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 - ## 另请参阅 - [优化向量搜索性能](/vector-search-improve-performance.md) From 894fcd4ca9d8d484879c58356bb257ca2d15b9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 19 Sep 2024 15:11:11 +0800 Subject: [PATCH 053/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 75c6be9226db..d269c21c86c7 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -71,8 +71,8 @@ CREATE TABLE vector_table ( embedding VECTOR ); -INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 3 dimensions vector, OK -INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 2 dimensions vector, OK +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),因为只有维度相同的向量之间才能计算向量距离。 From 92e1aeef73f7d1927b16a2d4fe897471d293fb14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 23 Sep 2024 09:50:33 +0800 Subject: [PATCH 054/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index d269c21c86c7..6ec0b8db0e50 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -92,15 +92,11 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 插入一个 2 维 - 两个向量中的各个元素逐一进行数值比较。 - 当遇到第一个不同的元素时,它们之间的数值比较结果即为两个向量之间的比较结果。 -- 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。 +- 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。例如,`[1,2,3] < [1,2,3,0]`。 - 长度相同且各个元素相同的两个向量 _相等_ 。 -- 空向量 _小于_ 任何非空向量。 +- 空向量 _小于_ 任何非空向量。例如,`[] < [1]`。 - 两个空向量 _相等_ 。 -示例: - -- `[] < [1]` -- `[1,2,3] < [1,2,3,0]` 在进行向量比较时,请使用[显式转换](#类型转换-cast)将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: From 0f91e5a3d841af0c3a3abce2a83d5b860294bd93 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Tue, 24 Sep 2024 11:35:13 +0800 Subject: [PATCH 055/109] Apply suggestions from code review --- vector-search-functions-and-operators.md | 2 +- vector-search-get-started-using-python.md | 2 +- vector-search-get-started-using-sql.md | 10 ++++++---- vector-search-improve-performance.md | 2 +- vector-search-index.md | 8 ++++---- vector-search-integrate-with-django-orm.md | 4 ++-- ...r-search-integrate-with-jinaai-embedding.md | 18 +++++++----------- vector-search-integrate-with-langchain.md | 18 ++++++++++-------- vector-search-integrate-with-llamaindex.md | 14 +++++++------- vector-search-integrate-with-peewee.md | 4 ++-- vector-search-integration-overview.md | 14 +++++++------- vector-search-limitations.md | 2 +- vector-search-overview.md | 2 +- 13 files changed, 50 insertions(+), 50 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 7d6865100f08..3add099d89e8 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -104,7 +104,7 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 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),使用的公式为: +计算两个向量之间的 [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}}}$ diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index 63b7e80f043d..af05d8053bb5 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -59,7 +59,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv
-对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: ```dotenv TIDB_DATABASE_URL="mysql+pymysql://:@:/" diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index f3eccebe547b..15751adc0ffa 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -1,6 +1,6 @@ --- title: 使用 SQL 开始向量搜索 -summary: 了解如何使用 SQL 语句快速开始使用 TiDB Cloud 中的向量搜索,并为生成式人工智能应用提供动力。 +summary: 了解如何在 TiDB 中使用 SQL 语句快速开始向量搜索,从而为你的生成式 AI 应用提供支持。 --- # 使用 SQL 开始向量搜索 @@ -52,6 +52,8 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md)
+对于 TiDB Cloud Serverless 集群,可以按照以下步骤连接到集群: + 1. 在 TiDB Cloud 的 [**Clusters**](https://tidbcloud.com/console/clusters) 页面,单击你的 TiDB Cloud Serverless 集群名,进入集群的 **Overview** 页面。 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 @@ -62,7 +64,7 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 5. 复制对话框中的连接命令,并粘贴到终端中执行。以下为 macOS 上的连接命令示例: - ```bash + ```bash mysql -u '.root' -h '' -P 4000 -D 'test' --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p'' ``` @@ -95,7 +97,7 @@ Query OK, 0 rows affected (0.27 sec) ### 第 3 步:向表中插入向量 -向 `embedded_documents` 表中插入三行包含[向量](/vector-search-overview.md#向量嵌入)的数据: +向 `embedded_documents` 表中插入三行,每一行包含数据和数据的[向量嵌入](/vector-search-overview.md#向量嵌入): ```sql INSERT INTO embedded_documents @@ -145,7 +147,7 @@ SELECT * FROM embedded_documents; 在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用[嵌入模型](/vector-search-overview.md#嵌入模型)将用户的搜索词转换为向量。 -执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量 (余弦距离最小) 的前三个向量。 +执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量(余弦距离最小)的前三个向量。 ```sql SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 979ce78bbb6c..7c446085cb6d 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -23,7 +23,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 随着向量维度大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 -为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,你需要确保改变嵌入模型对向量查询准确性的影响。 +为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,你需要评估改变嵌入模型对向量查询准确性的影响。 一些嵌入模型,如 OpenAI `text-embedding-3-large`,支持[缩短向量嵌入](https://openai.com/index/new-embedding-models-and-api-updates/),即在不丢失向量表示的概念特征的情况下,从向量序列末尾移除一些数字。你也可以使用这种嵌入模型来减少向量维数。 diff --git a/vector-search-index.md b/vector-search-index.md index 335165b1cc57..08a65d19e5ad 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -54,7 +54,7 @@ TiDB 目前支持以下向量搜索索引算法: > **Note:** > -> 创建向量索引目前为实验特性,其语法可能会在 GA 前发生变化。 +> 向量索引目前为实验特性,其语法可能会在 GA 前发生变化。 在创建 HNSW 向量索引时,你需要指定向量的距离函数: @@ -76,11 +76,11 @@ ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') LIMIT 10 ``` -要在向量搜索中使用索引,请确保 `ORDER BY ... LIMIT` 子句中使用的距离函数与创建向量索引时 `HNSW ()` 中指定的距离函数相同。 +要在向量搜索中使用索引,请确保 `ORDER BY ... LIMIT` 子句中使用的距离函数与创建向量索引时指定的距离函数相同。 ## 使用带过滤条件的向量搜索索引 -包含预过滤条件 (使用 `WHERE` 子句) 的查询无法使用向量搜索索引,因为这样的查询并没有严格按照 SQL 语义来查询 K 近邻。 +包含预过滤条件(使用 `WHERE` 子句)的查询无法使用向量搜索索引,因为这样的查询并没有严格按照 SQL 语义来查询 K 近邻。例如: ```sql -- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: @@ -175,7 +175,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 更多信息,请参阅 [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md)。 -同时,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 `DDL job` 执行进度,观察其 `row count`。 不过这种方式并不准确,`row count` 的值是从 `TIFLASH_INDEXES` 里的 `rows_stable_indexed` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 +此外,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 DDL 任务的执行进度,观察其 `row count`。 不过这种方式并不准确,`row count` 的值是从 `TIFLASH_INDEXES` 里的 `rows_stable_indexed` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 ## 查看是否使用了向量搜索索引 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 2966271e65fd..da9b95568923 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -78,7 +78,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv
-对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: ```dotenv TIDB_HOST=127.0.0.1 @@ -211,7 +211,7 @@ if TIDB_CA_PATH: #### 定义向量列 -`tidb-django` 提供了一个 `VectorField` ,可以在表中用来表示和存储向量类型。 +`tidb-django` 提供了一个 `VectorField`,可以在表中用来表示和存储向量类型。 创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index d251879e493a..58379354595d 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -56,11 +56,7 @@ pip install -r requirements.txt ### 第 4 步:配置环境变量 -#### 4.1 获取 Jina AI API 密钥 - -从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥。 - -#### 4.2 配置 TiDB 连接参数 +从 [Jina AI Embeddings API](https://jina.ai/embeddings/) 页面获取 Jina AI API 密钥,然后根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 @@ -74,15 +70,15 @@ export TIDB_DATABASE_URL="mysql+pymysql://:@:/`:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。
diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index 7025a7ca072e..f625a6a4e66f 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -11,7 +11,7 @@ summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 > > 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 -> **Note** +> **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) 在线环境中运行示例代码。 @@ -63,6 +63,8 @@ from langchain_text_splitters import CharacterTextSplitter ### 第 3 步:配置环境变量 +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 +
@@ -93,11 +95,11 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/`:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。
@@ -147,7 +149,7 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/ -### 检索器 +### 用作检索器 在 Langchain 中,[检索器](https://python.langchain.com/v0.2/docs/concepts/#retrievers)是一个接口,用于响应非结构化查询,检索相关文档。相比于向量存储,检索器可以为你提供更多的功能。以下代码演示了如何将 TiDB 向量存储用作检索器。 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 5c319715681e..095e71cc393e 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -11,7 +11,7 @@ summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 > > 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 -> **Note** +> **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) 在线环境中运行示例代码。 @@ -92,11 +92,11 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/`:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 +- ``:连接 TiDB 集群的用户名。 +- ``:连接 TiDB 集群的密码。 +- ``:要连接的数据库名称。
@@ -146,7 +146,7 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/ -对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的启动参数修改环境变量值为 TiDB 实际对应的值: +对于本地部署的 TiDB,请在 Python 项目的根目录下新建一个 `.env` 文件,将以下内容复制到 `.env` 文件中,并根据集群的连接参数修改环境变量值为 TiDB 实际对应的值: ```dotenv TIDB_HOST=127.0.0.1 @@ -85,7 +85,7 @@ TIDB_DATABASE=test - `TIDB_HOST`:TiDB 集群的主机号。 - `TIDB_PORT`:TiDB 集群的端口号。 - `TIDB_USERNAME`:连接 TiDB 集群的用户名。 -- `TIDB_PASSWORD`:连接 TiDB 集群的密码。集群初始密码为空,第一次启动集群时无需带上此字段。 +- `TIDB_PASSWORD`:连接 TiDB 集群的密码。 - `TIDB_DATABASE`:要连接的数据库名称。
diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index d02a4b0cf6ab..4a4974f2d871 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -13,14 +13,14 @@ summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库 ## AI 框架 -TiDB 目前支持以下 AI 框架。在这些 AI 框架下,你可以使用 TiDB 向量搜索构建 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 完成多种其它需求,例如将 TiDB 用于 AI 应用程序的文档存储和知识图谱存储等。 ## 嵌入模型和服务 @@ -32,11 +32,11 @@ TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌 | 嵌入模型服务提供商 | 教程 | |-----------------------------|---------------------------------------------------------------------------------------------------------------------| -| Jina AI | [通过Jina AI 嵌入 API 使用向量搜索](/vector-search-integrate-with-jinaai-embedding.md) | +| Jina AI | [结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索](/vector-search-integrate-with-jinaai-embedding.md) | ## 对象关系映射 (ORM) 库 -你可以通过结合 ORM 库使用 TiDB 向量搜索,以便与 TiDB 数据库交互。 +你可以将 TiDB 向量搜索功能与 ORM 库结合使用,以便与 TiDB 数据库交互。 下表列出了支持的 ORM 库和相应的使用教程: @@ -56,16 +56,16 @@ TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌 SQLAlchemy pip install tidb-vector - TiDB 向量搜索在 SQLAlchemy 中的使用 + 在 SQLAlchemy 中使用 TiDB 向量搜索 peewee pip install tidb-vector -
TiDB 向量搜索在 peewee 中的使用 + 在 peewee 中使用 TiDB 向量搜索 Django pip install django-tidb[vector] - TiDB 向量搜索在 Django 中的使用 + 在 Django 中使用 TiDB 向量搜索 \ No newline at end of file diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 21e21631926e..31876943e188 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -14,7 +14,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 - 创建[向量搜索索引](/vector-search-index.md)时,只支持余弦距离和 L2 距离 (欧氏距离)这两种距离度量方法。 -- 目前,向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量字段插入或存储数据时,如果这些数据的类型是双精度浮点数,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 +- 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 ## 反馈 diff --git a/vector-search-overview.md b/vector-search-overview.md index 30b1827ec4f6..157dbcd53e17 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -45,7 +45,7 @@ TiDB 向量搜索 (Vector Search) 通过使用[距离函数](/vector-search-func ![The Schematic TiDB Vector Search](/media/vector-search/embedding-search.png) - TiDB 作为一款关系型数据库,在引入了向量搜索功能后,支持将数据及其对应的向量表示(向量嵌入)存储在同一个数据库中。你可以选择以下任一种存储方式: +TiDB 作为一款关系型数据库,在引入了向量搜索功能后,支持将数据及其对应的向量表示(向量嵌入)存储在同一个数据库中。你可以选择以下任一种存储方式: - 将数据和对应的向量表示存储在同一张表的不同列中。 - 将数据和对应的向量表示分别存储在不同的表中。在进行搜索时,通过 JOIN 查询将这些表关联起来。 From 39958f3e931f5804a69ba2328d92c721ca772220 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Tue, 24 Sep 2024 12:00:03 +0800 Subject: [PATCH 056/109] UI changes: Endpoint Type -> Connection Type --- vector-search-get-started-using-python.md | 2 +- vector-search-get-started-using-sql.md | 2 +- vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-peewee.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index af05d8053bb5..cabeebf12d68 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -88,7 +88,7 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/" 3. 确认对话框中的配置和你的运行环境一致。 - - **Endpoint Type** 为 `Public`。 + - **Connection Type** 为 `Public`。 - **Branch** 选择 `main`。 - **Connect With** 选择 `SQLAlchemy`。 - **Operating System** 为你的运行环境。 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index 15751adc0ffa..fe2010885e84 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -58,7 +58,7 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 2. 点击右上角的 **Connect** 按钮,将会弹出连接对话框。 -3. 在连接对话框中,选择 **Connect With** 下拉列表中的 **MySQL CLI**,并保留 **Endpoint Type** 的默认值为 **Public**。 +3. 在连接对话框中,选择 **Connect With** 下拉列表中的 **MySQL CLI**,并保留 **Connection Type** 的默认值为 **Public**。 4. 如果你还没有设置密码,点击 **Generate Password** 生成一个随机密码。 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index da9b95568923..e6fded98fccc 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -110,7 +110,7 @@ TIDB_DATABASE=test 3. 确认对话框中的配置和你的运行环境一致。 - - **Endpoint Type** 为 `Public`。 + - **Connection Type** 为 `Public`。 - **Branch** 选择 `main`。 - **Connect With** 选择 `General`。 - **Operating System** 为你的运行环境。 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index dd20fe594a84..58e80c186786 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -100,7 +100,7 @@ TIDB_DATABASE=test 3. 确认对话框中的配置和你的运行环境一致。 - - **Endpoint Type** 设置为 `Public` + - **Connection Type** 设置为 `Public` - **Branch** 设置为 `main` - **Connect With** 设置为 `General` - **Operating System** 与你的机器环境相匹配 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 8c5108e09dbc..5aae29e0c61e 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -97,7 +97,7 @@ TIDB_DATABASE_URL=mysql+pymysql://:@:/ 3. 确认对话框中的配置和你的运行环境一致。 - - **Endpoint Type** 为 `Public`。 + - **Connection Type** 为 `Public`。 - **Branch** 选择 `main`。 - **Connect With** 选择 `General`。 - **Operating System** 为你的运行环境。 From f8af8f688acfb595e9304958ea6c4eee1ce2b8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 24 Sep 2024 16:46:55 +0800 Subject: [PATCH 057/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 1 + vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-peewee.md | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 08a65d19e5ad..51e3ae313c64 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -25,6 +25,7 @@ TiDB 目前支持以下向量搜索索引算法: - 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 - 不支持删除具有向量搜索索引的列,也不支持同时创建多个索引。 +- 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 - 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 ## 创建 HNSW 向量搜索索引 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index e6fded98fccc..8d9f54e41a02 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -205,7 +205,7 @@ if TIDB_CA_PATH: } ``` -你可以在项目的根目录下创建一个 `.env` 文件,在文件中添加环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`,并根据你的TiDB 集群的实际值来设置这些变量的值。 +你可以在项目的根目录下创建一个 `.env` 文件,在文件中添加环境变量 `TIDB_HOST`、`TIDB_PORT`、`TIDB_USERNAME`、`TIDB_PASSWORD`、`TIDB_DATABASE` 和 `TIDB_CA_PATH`,并根据你的 TiDB 集群的实际值来设置这些变量的值。 ### 创建向量表 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 58e80c186786..0d3adfadb957 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -189,7 +189,9 @@ connect_kwargs = { # connect_kwargs = { # 'ssl_mode': 'VERIFY_IDENTITY', # 'ssl': { -# # Root certificate default path +# # 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'), # }, From 12abce85f0b3d2b73294fdb5042c697996aae0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 24 Sep 2024 16:49:45 +0800 Subject: [PATCH 058/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index 51e3ae313c64..f404680a562a 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -24,7 +24,7 @@ TiDB 目前支持以下向量搜索索引算法: - 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 - 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 -- 不支持删除具有向量搜索索引的列,也不支持同时创建多个索引。 +- 不支持删除具有向量搜索索引的列,也不支持在同一个 SQL 语句中创建多个索引。 - 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 - 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 From c9ef22f709743aef4c221931f2082656407b98f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 25 Sep 2024 09:52:19 +0800 Subject: [PATCH 059/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 24 +++++++++---------- ...-search-integrate-with-jinaai-embedding.md | 8 +++---- vector-search-integrate-with-langchain.md | 6 ++--- vector-search-integrate-with-llamaindex.md | 6 ++--- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index f404680a562a..c5c8959ce1ad 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -13,16 +13,14 @@ K 近邻(K-Nearest Neighbors,简称 KNN)搜索是一种在向量空间中 > > 向量搜索索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 -TiDB 目前支持以下向量搜索索引算法: - -- HNSW +TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 向量搜索索引算法。 ## 使用限制 - 集群需要提前部署 TiFlash 节点。 - 向量搜索索引不能作为主键或者唯一索引。 - 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 -- 创建和使用搜索向量索引时需要指定距离函数(目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`)。 +- 创建和使用搜索向量索引时需要指定距离函数。目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 - 不支持删除具有向量搜索索引的列,也不支持在同一个 SQL 语句中创建多个索引。 - 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 @@ -30,7 +28,7 @@ TiDB 目前支持以下向量搜索索引算法: ## 创建 HNSW 向量搜索索引 -[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是当前最流行的向量搜索索引算法之一。它性能良好,而且准确率相对较高 (特定情况下可达 98%)。 +[HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 是当前最流行的向量搜索索引算法之一。它性能良好,而且准确率相对较高,特定情况下可达 98%。 在 TiDB 中,你可以通过以下任一种方式为[向量数据类型](/vector-search-data-types.md)的列创建 HNSW 索引。 @@ -53,9 +51,9 @@ TiDB 目前支持以下向量搜索索引算法: ALTER TABLE foo ADD VECTOR INDEX idx_name ((VEC_COSINE_DISTANCE(data))) USING HNSW; ``` -> **Note:** +> **注意:** > -> 向量索引目前为实验特性,其语法可能会在 GA 前发生变化。 +> 向量搜索索引目前为实验特性,其语法可能会在 GA 前发生变化。 在创建 HNSW 向量索引时,你需要指定向量的距离函数: @@ -94,7 +92,7 @@ LIMIT 5; 如需使用带过滤条件的向量搜索索引,可以采用以下几种方法: -**向量搜索后再过滤:** 先查询 K 个最近的邻居,再过滤掉不需要的结果: +**向量搜索后再过滤:** 先查询 K 个最近的邻居,再过滤掉不需要的结果: ```sql -- 对于以下查询,过滤条件是在 KNN 之后执行的,因此可以使用向量索引: @@ -110,7 +108,7 @@ WHERE category = "document"; -- 请注意,如果过滤掉一些结果,此查询返回的结果可能少于 5 个。 ``` -**对表进行分区**: 在[分区](/partitioned-table.md)内的查询可以充分利用向量索引。如果你需要进行等值过滤,这会非常有用,因为等值过滤可以转化为访问指定的分区。 +**对表进行分区:**在[分区表](/partitioned-table.md)内的查询可以充分利用向量索引。如果你需要进行等值过滤,会非常有用,因为等值过滤可以转化为访问指定的分区。 例如,假设你需要查找与特定产品版本最接近的文档: @@ -176,7 +174,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 更多信息,请参阅 [`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` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 +此外,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 DDL 任务的执行进度,观察其 `row count`。不过这种方式并不准确,`row count` 的值是从 `TIFLASH_INDEXES` 里的 `rows_stable_indexed` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 ## 查看是否使用了向量搜索索引 @@ -268,7 +266,7 @@ LIMIT 10; +-----+--------------------------------------------------------+-----+ ``` -> **Note:** +> **注意:** > > 执行信息为 TiDB 内部信息。字段和格式如有更改,恕不另行通知。请勿依赖。 @@ -276,12 +274,12 @@ LIMIT 10; - `vector_index.load.total`:加载索引的总时长。该字段的值可能会超过查询实际耗时,因为 TiDB 可能会并行加载多个向量索引。 - `vector_index.load.from_s3`:从 S3 加载的索引数量。 -- `vector_index.load.from_disk`:从磁盘加载的索引数量。这些索引之前已经从 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)。 +关于执行信息输出的更多信息,请参阅 [`EXPLAIN`](/sql-statements/sql-statement-explain.md)、[`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md),以及[使用 `EXPLAIN` 解读执行计划](/explain-walkthrough.md)。 ## 另请参阅 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 58379354595d..c360a24ef7db 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -92,9 +92,9 @@ export TIDB_DATABASE_URL="mysql+pymysql://:@:/ **Tip:** @@ -214,7 +214,7 @@ class Document(Base): ) ``` -> **Note:** +> **注意:** > > - 向量列的维度必须与嵌入模型生成的向量嵌入维度相同。 > - 在本例中,`jina-embeddings-v2-base-en` 模型生成的向量嵌入维度为 `768`。 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index f625a6a4e66f..b87518db90d5 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -114,8 +114,8 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/ **Note** +> **注意:** > > `TiDBVectorStore` 只支持 [`default`](https://docs.llamaindex.ai/en/stable/api_reference/storage/vector_store/?h=vectorstorequerymode#llama_index.core.vector_stores.types.VectorStoreQueryMode) 查询模式。 From 3350c1066c2fa7681c717695615e0f45c338150f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Thu, 26 Sep 2024 15:15:36 +0800 Subject: [PATCH 060/109] remove 'vector64()' sytax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index c5c8959ce1ad..a35d6934cf19 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -38,7 +38,6 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped CREATE TABLE foo ( id INT PRIMARY KEY, data VECTOR(5), - data64 VECTOR64(10), VECTOR INDEX idx_data USING HNSW ((VEC_COSINE_DISTANCE(data))) ); ``` From f18d840f8148e2966150aaef939025a92cbae0c2 Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Fri, 27 Sep 2024 17:23:26 +0800 Subject: [PATCH 061/109] Update desc about tiflash upgrade Signed-off-by: JaySon-Huang --- tiflash-upgrade-guide.md | 4 ++++ 1 file changed, 4 insertions(+) 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-节点)。 From 9cbc09e46800b17b13855f323c4bcac2a34c22ff Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Sun, 29 Sep 2024 11:31:33 +0800 Subject: [PATCH 062/109] Update desc about br support Signed-off-by: JaySon-Huang --- br/backup-and-restore-overview.md | 1 + 1 file changed, 1 insertion(+) 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 集群。 | ### 版本间兼容性 From 13bc862e5d24e8a3eead82bcdbdc07e741a3e52e Mon Sep 17 00:00:00 2001 From: JaySon Date: Sun, 29 Sep 2024 11:32:45 +0800 Subject: [PATCH 063/109] Add limitation about BR restore --- vector-search-limitations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 31876943e188..c9a6028027bf 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -15,7 +15,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 - 创建[向量搜索索引](/vector-search-index.md)时,只支持余弦距离和 L2 距离 (欧氏距离)这两种距离度量方法。 - 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 - +- 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 ## 反馈 我们非常重视您的反馈意见。如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file From 7704118a7124a9c39426f3b735b5578c2d4c1f4b Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Sun, 29 Sep 2024 11:48:39 +0800 Subject: [PATCH 064/109] Update desc about limitation Signed-off-by: JaySon-Huang --- dm/dm-overview.md | 4 ++++ vector-search-limitations.md | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) 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/vector-search-limitations.md b/vector-search-limitations.md index c9a6028027bf..931d93527c78 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -13,9 +13,11 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 创建[向量搜索索引](/vector-search-index.md)时,只支持余弦距离和 L2 距离 (欧氏距离)这两种距离度量方法。 +- 创建[向量搜索索引](/vector-search-index.md)时的限制,参照[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 - 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 - 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 +- DM 不支持 MySQL 9.0 的向量数据类型同步。 + ## 反馈 -我们非常重视您的反馈意见。如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 \ No newline at end of file +我们非常重视您的反馈意见。如果在开发的过程中遇到问题,可以在 [AskTUG](https://asktug.com/?utm_source=docs-cn-dev-guide) 上进行提问,寻求帮助。 From d135903b97a751d3354156a14ea1b1c671c50616 Mon Sep 17 00:00:00 2001 From: wk989898 Date: Sun, 29 Sep 2024 14:50:54 +0800 Subject: [PATCH 065/109] add limit about cdc --- ticdc/ticdc-compatibility.md | 8 ++++++++ vector-search-limitations.md | 1 + 2 files changed, 9 insertions(+) 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/vector-search-limitations.md b/vector-search-limitations.md index 931d93527c78..1c9fae0338b7 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -17,6 +17,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 - 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 - DM 不支持 MySQL 9.0 的向量数据类型同步。 +- CDC 对于不支持向量数据的下游会修改数据类型。参照[向量搜索功能兼容性说明](/ticdc/ticdc-compatibility.md#向量搜索功能兼容性说明实验特性) ## 反馈 From f374485de2ca41d5ae5b9ed754477b826e6bd669 Mon Sep 17 00:00:00 2001 From: JaySon-Huang Date: Sun, 29 Sep 2024 17:45:42 +0800 Subject: [PATCH 066/109] Update tiflash-configuration Signed-off-by: JaySon-Huang --- tiflash/tiflash-configuration.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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% 以上。 From 2ba7811486d60cb3125b6fe932e5e3d0e7189ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 30 Sep 2024 10:11:05 +0800 Subject: [PATCH 067/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index a35d6934cf19..83e271adb7e5 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -1,6 +1,6 @@ --- title: 向量搜索索引 -summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (KNN) 查询。 +summary: 了解如何在 TiDB 中构建并使用向量搜索索引加速 K 近邻 (K-Nearest Neighbors, KNN) 查询。 --- # 向量搜索索引 From c7fedb4bc9c177752e7b48763a0a7b2d310680fd Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:06:32 +0800 Subject: [PATCH 068/109] Apply suggestions from code review Co-authored-by: Grace Cai Co-authored-by: JaySon --- vector-search-data-types.md | 8 ++++---- vector-search-limitations.md | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 6ec0b8db0e50..fc581f1eb072 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -153,10 +153,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 可以使用以下函数在向量和字符串之间进行转换: -- `CAST(... AS VECTOR)`: 将字符串类型转换为向量类型 -- `CAST(... AS CHAR)`: 将向量类型转换为字符串类型 -- `VEC_FROM_TEXT`: 将字符串类型转换为向量类型 -- `VEC_AS_TEXT`: 将向量类型转换为字符串类型 +- `CAST(... AS VECTOR)`:将字符串类型转换为向量类型 +- `CAST(... AS CHAR)`:将向量类型转换为字符串类型 +- `VEC_FROM_TEXT`:将字符串类型转换为向量类型 +- `VEC_AS_TEXT`:将向量类型转换为字符串类型 出于易用性考虑,如果你使用的函数只支持向量数据类型(例如,向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换: diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 1c9fae0338b7..4ced63014376 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -13,6 +13,9 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 +- 向量列不能作为主键或者主键的一部分 +- 向量列不能作为唯一索引或者唯一索引的一部分 +- 向量列不能作为分区键或者分区键的一部分 - 创建[向量搜索索引](/vector-search-index.md)时的限制,参照[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 - 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 - 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 From 28164e76715dc52ed2bbfdf8fa1969ba3da1bda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 8 Oct 2024 10:52:51 +0800 Subject: [PATCH 069/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 83e271adb7e5..e3e8831a3552 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -22,9 +22,9 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped - 向量搜索索引只能基于单一的向量列创建,不能与其他列(如整数列或字符串列)组合形成复合索引。 - 创建和使用搜索向量索引时需要指定距离函数。目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 -- 不支持删除具有向量搜索索引的列,也不支持在同一个 SQL 语句中创建多个索引。 +- 不支持直接删除具有向量搜索索引的列。可以通过先删除列上的向量搜索索引,再删除列的方式完成删除。 - 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 -- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 +- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)(该功能计划在未来的版本中支持)。 ## 创建 HNSW 向量搜索索引 @@ -50,9 +50,6 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped ALTER TABLE foo ADD VECTOR INDEX idx_name ((VEC_COSINE_DISTANCE(data))) USING HNSW; ``` -> **注意:** -> -> 向量搜索索引目前为实验特性,其语法可能会在 GA 前发生变化。 在创建 HNSW 向量索引时,你需要指定向量的距离函数: @@ -173,7 +170,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 更多信息,请参阅 [`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` 获取的。此方式也可作为你查看索引构建进度的一种参考方式。 +此外,你也可以通过 `ADMIN SHOW DDL JOBS;` 查看 DDL 任务的执行进度,观察其 `row count`。不过这种方式并不准确,`row count` 的值是从 `TIFLASH_INDEXES` 里的 `rows_stable_indexed` 获取的。你也可以使用此方式查看索引构建进度。 ## 查看是否使用了向量搜索索引 From 95338ee29ccd9a99b21cd3454556ecc347124015 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 9 Oct 2024 15:01:26 +0800 Subject: [PATCH 070/109] Update TOC.md --- TOC.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/TOC.md b/TOC.md index b684c57d49bd..2a21e26b8489 100644 --- a/TOC.md +++ b/TOC.md @@ -77,6 +77,24 @@ - [Follower Read](/develop/dev-guide-use-follower-read.md) - [Stale Read](/develop/dev-guide-use-stale-read.md) - [HTAP 查询](/develop/dev-guide-hybrid-oltp-and-olap-queries.md) + - 向量搜索 + - [概述](/vector-search-overview.md) + - 快速入门 + - [使用 SQL 开始向量搜索](/vector-search-get-started-using-sql.md) + - [使用 Python 开始向量搜索](/vector-search-get-started-using-python.md) + - 集成 + - [集成概览](/vector-search-integration-overview.md) + - AI 框架 + - [LlamaIndex](/vector-search-integrate-with-llamaindex.md) + - [Langchain](/vector-search-integrate-with-langchain.md) + - 嵌入模型/服务 + - [Jina AI](/vector-search-integrate-with-jinaai-embedding.md) + - ORM 库 + - [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) + - [peewee](/vector-search-integrate-with-peewee.md) + - [Django ORM](/vector-search-integrate-with-django-orm.md) + - [提升搜索性能](/vector-search-improve-performance.md) + - [使用限制](/vector-search-limitations.md) - 事务 - [概览](/develop/dev-guide-transaction-overview.md) - [乐观事务和悲观事务](/develop/dev-guide-optimistic-and-pessimistic-transaction.md) @@ -875,6 +893,7 @@ - [日期和时间类型](/data-type-date-and-time.md) - [字符串类型](/data-type-string.md) - [JSON 类型](/data-type-json.md) + - [向量数据类型](/vector-search-data-types.md) - 函数与操作符 - [函数与操作符概述](/functions-and-operators/functions-and-operators-overview.md) - [表达式求值的类型转换](/functions-and-operators/type-conversion-in-expression-evaluation.md) @@ -888,6 +907,7 @@ - [加密和压缩函数](/functions-and-operators/encryption-and-compression-functions.md) - [锁函数](/functions-and-operators/locking-functions.md) - [信息函数](/functions-and-operators/information-functions.md) + - [向量函数和操作符](/vector-search-functions-and-operators.md) - JSON 函数 - [概览](/functions-and-operators/json-functions.md) - [创建 JSON 的函数](/functions-and-operators/json-functions/json-functions-create.md) @@ -908,6 +928,7 @@ - [TiDB 特有的函数](/functions-and-operators/tidb-functions.md) - [Oracle 与 TiDB 函数和语法差异对照](/oracle-functions-to-tidb.md) - [聚簇索引](/clustered-indexes.md) + - [向量索引](/vector-search-index.md) - [约束](/constraints.md) - [生成列](/generated-columns.md) - [SQL 模式](/sql-mode.md) From 1b5fa2f5002d24da403877e34616f082ff23ec4e Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:43:47 +0800 Subject: [PATCH 071/109] Apply suggestions from code review Co-authored-by: Grace Cai Co-authored-by: Lynn --- ticdc/ticdc-compatibility.md | 8 ++++---- vector-search-index.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ticdc/ticdc-compatibility.md b/ticdc/ticdc-compatibility.md index ffe9026ef6ae..95446d460c26 100644 --- a/ticdc/ticdc-compatibility.md +++ b/ticdc/ticdc-compatibility.md @@ -66,10 +66,10 @@ TiCDC 从 v5.3.0 开始支持[全局临时表](/temporary-tables.md#全局临时 如果 TiCDC 的上游集群包含全局临时表,下游集群也必须是 TiDB 5.3.0 及以上版本,否则同步报错。 -### 向量搜索功能兼容性说明(实验特性) +### 向量数据类型兼容性说明 -TiCDC 从 v8.4.0 开始支持[向量搜索功能](/vector-search-overview.md)。 +从 v8.4.0 开始,TiCDC 支持同步包含[向量数据类型](/vector-search-data-types.md)的表到下游(实验特性)。 -写入下游为 Kafka 或者存储服务(如:Amazon S3、GCS、Azure Blob Storage 和 NFS)时,会将向量类型转为字符串类型。 +当下游为 Kafka 或者存储服务(如:Amazon S3、GCS、Azure Blob Storage 和 NFS)时,TiCDC 会将向量数据类型转为字符串类型进行写入。 -写入到不支持向量类型的 MySQL 兼容数据库时, 涉及向量类型的 DDL 事件无法成功写入。在`sink-url`中添加配置参数`has-vector-type=true`后,会将向量类型转为 `LONGTEXT` 类型进行写入。 \ No newline at end of file +当下游为不支持向量类型的 MySQL 兼容数据库时,涉及向量类型的 DDL 事件无法成功写入。在这种情况下,请在 `sink-url` 中添加配置参数 `has-vector-type=true`,然后 TiCDC 会将向量数据类型转为 `LONGTEXT` 类型进行写入。 \ No newline at end of file diff --git a/vector-search-index.md b/vector-search-index.md index e3e8831a3552..955e6cdfbaab 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -23,8 +23,8 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped - 创建和使用搜索向量索引时需要指定距离函数。目前只支持余弦距离函数 `VEC_COSINE_DISTANCE()` 和 L2 距离函数 `VEC_L2_DISTANCE()`。 - 不支持在同一列上创建多个使用了相同距离函数的向量搜索索引。 - 不支持直接删除具有向量搜索索引的列。可以通过先删除列上的向量搜索索引,再删除列的方式完成删除。 -- 不支持修改带有向量索引的列的类型(有损变更,即修改了列数据)。 -- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)(该功能计划在未来的版本中支持)。 +- 不支持修改带有向量索引的列的类型。 +- 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 ## 创建 HNSW 向量搜索索引 @@ -53,10 +53,10 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 在创建 HNSW 向量索引时,你需要指定向量的距离函数: -- 余弦距离:`((VEC_COSINE_DISTANCE(cols_name))) USING HNSW` -- L2 距离:`((VEC_L2_DISTANCE(cols_name))) USING HNSW` +- 余弦距离:`((VEC_COSINE_DISTANCE(col_name))) USING HNSW` +- L2 距离:`((VEC_L2_DISTANCE(col_name))) USING HNSW` -你只能为固定维度的向量列 (如 `VECTOR(3)` ) 创建向量索引,不能为混合维度的向量列 (如 `VECTOR` ) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 +你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 有关向量搜索索引的约束和限制,请参阅[向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束)。 From 03d3cb57d2058b894042b65982002718111568f9 Mon Sep 17 00:00:00 2001 From: JaySon Date: Wed, 9 Oct 2024 21:35:06 +0800 Subject: [PATCH 072/109] Apply suggestions from code review Co-authored-by: Grace Cai --- br/backup-and-restore-overview.md | 2 +- dm/dm-overview.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/br/backup-and-restore-overview.md b/br/backup-and-restore-overview.md index 2eefca83608a..f328f33033c9 100644 --- a/br/backup-and-restore-overview.md +++ b/br/backup-and-restore-overview.md @@ -120,7 +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 集群。 | +| 向量搜索 | | 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的表恢复至 v8.4.0 之前的 TiDB 集群。 | ### 版本间兼容性 diff --git a/dm/dm-overview.md b/dm/dm-overview.md index 2c0d526279da..8219229cb344 100644 --- a/dm/dm-overview.md +++ b/dm/dm-overview.md @@ -62,7 +62,7 @@ tiup install dm dmctl + 向量类型数据同步 - - DM 不支持 MySQL 9.0 的向量数据类型同步。 + - DM 不支持迁移或同步 MySQL 9.0 的向量数据类型到 TiDB。 ## Contributing From 1c39b3730fc474d851170636f3bed585a63f3bbe Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 10 Oct 2024 12:11:49 +0800 Subject: [PATCH 073/109] Add limitation about encryption-at-rest --- vector-search-index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/vector-search-index.md b/vector-search-index.md index 955e6cdfbaab..a55bc23f87ce 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -25,6 +25,7 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped - 不支持直接删除具有向量搜索索引的列。可以通过先删除列上的向量搜索索引,再删除列的方式完成删除。 - 不支持修改带有向量索引的列的类型。 - 不支持将向量搜索索引[设置为不可见](/sql-statements/sql-statement-alter-index.md)。 +- 不支持在开启了[静态加密](/encryption-at-rest.md)的 TiFlash 节点上构建向量搜索索引。 ## 创建 HNSW 向量搜索索引 From 0010207f44f095a6850022b4d72e9d21e4a4d88a Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Thu, 10 Oct 2024 15:24:01 +0800 Subject: [PATCH 074/109] Update format --- vector-search-functions-and-operators.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 3add099d89e8..c1e74ef15e9f 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -15,7 +15,7 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量函数: -**向量距离函数** +**向量距离函数:** | 函数名 | 描述 | | --------------------------------------------------------- | ----------------------------------------------------------- | @@ -24,7 +24,7 @@ TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量 | [VEC_NEGATIVE_INNER_PRODUCT](#vec_negative_inner_product) | 计算两个向量内积的负数 | | [VEC_L1_DISTANCE](#vec_l1_distance) | 计算两个向量之间的 L1 距离 (曼哈顿距离) | -**其他向量函数** +**其他向量函数:** | 函数名 | Description | | ------------------------------- | --------------------------------------------------- | @@ -37,7 +37,7 @@ TiDB 为[向量数据类型](/vector-search-data-types.md)引入了以下向量 TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了[向量数据类型](/vector-search-data-types.md)。 -**算术运算符** +**算术运算符:** | 运算符 | 描述 | | :-------------------------------------------------------------------------------------- | :--------------------------------------- | @@ -46,7 +46,7 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 关于向量运算工作原理的更多信息,请参阅[向量数据类型的运算](/vector-search-data-types.md#运算)。 -**聚合函数 (GROUP BY)** +**聚合函数 (GROUP BY):** | 函数名 | 描述 | | :------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | @@ -55,7 +55,7 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 | [`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) | 返回最小值 | -**比较函数与操作符** +**比较函数与操作符:** | 名称 | 描述 | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | @@ -78,7 +78,7 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 关于如何比较向量的更多信息,请参阅[向量数据类型的比较](/vector-search-data-types.md#比较)。 -**控制流程函数** +**控制流程函数:** | 函数名 | 描述 | | :------------------------------------------------------------------------------------------------ | :--------------------------- | @@ -87,7 +87,7 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 | [`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` | -**转换函数** +**转换函数:** | 函数名 | 描述 | | :------------------------------------------------------------------------------------------ | :----------------------------- | From 9fee36aaf8adb68c58274a86c42ee55a982247c9 Mon Sep 17 00:00:00 2001 From: lilin90 Date: Thu, 10 Oct 2024 15:29:46 +0800 Subject: [PATCH 075/109] Update wording and format --- vector-search-functions-and-operators.md | 38 ++++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index c1e74ef15e9f..cdbe4989e71e 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -19,27 +19,27 @@ 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 距离 (曼哈顿距离) | +| [`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) | 将向量类型转换为字符串类型 | +| [`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)。 +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) | 向量以元素为单位进行减法运算符 | @@ -48,8 +48,8 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 **聚合函数 (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) | 返回最大值 | @@ -57,8 +57,8 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 **比较函数与操作符:** -| 名称 | 描述 | -| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| 名称 | 描述 | +| ------------------------------------- | ----------------------------------------------------- | | [`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) | 相等比较符 | @@ -80,8 +80,8 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 **控制流程函数:** -| 函数名 | 描述 | -| :------------------------------------------------------------------------------------------------ | :--------------------------- | +| 函数名 | 描述 | +| :--------------------------------------------- | :--------------------------- | | [`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 | @@ -89,8 +89,8 @@ TiDB 扩展了以下内置函数和运算符的功能,它们也额外支持了 **转换函数:** -| 函数名 | 描述 | -| :------------------------------------------------------------------------------------------ | :----------------------------- | +| 函数名 | 描述 | +| :----------------------------- | :----------------------------- | | [`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) | 将值转换为字符串类型 | From ad6eeb101f5d6fe4a5622eb2d066ba2817b280cd Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Thu, 10 Oct 2024 15:47:38 +0800 Subject: [PATCH 076/109] Remove description about future features --- vector-search-limitations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 4ced63014376..1917b89bb226 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -5,7 +5,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 # 向量搜索限制 -本文档介绍 TiDB 向量搜索的已知限制。在未来的版本中,我们会持续新增更多功能来提升使用体验。 +本文档介绍 TiDB 向量搜索的已知限制。 > **警告:** > From 44995da568a7edcd607f096a20267a65ff3352ba Mon Sep 17 00:00:00 2001 From: lilin90 Date: Thu, 10 Oct 2024 15:51:04 +0800 Subject: [PATCH 077/109] Update wording --- vector-search-limitations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 4ced63014376..3b50ed1e9747 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -9,7 +9,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 From 7fbbed33fcb4b866f7901e21e69b149b3219b862 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Thu, 10 Oct 2024 15:52:14 +0800 Subject: [PATCH 078/109] Update wording --- vector-search-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-overview.md b/vector-search-overview.md index 157dbcd53e17..e1f546f5ecc8 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -9,7 +9,7 @@ TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 概念 From f51d86058c7d8a5ace96b403006cff499cf34659 Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 10 Oct 2024 17:06:29 +0800 Subject: [PATCH 079/109] Using upper case VEC_COSINE_DISTANCE instead --- vector-search-index.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index a55bc23f87ce..800d2899dc12 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -67,8 +67,8 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped ```sql SELECT * -FROM vector_table_with_index -ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +FROM foo +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3, 4, 5]') LIMIT 10 ``` @@ -83,7 +83,7 @@ LIMIT 10 SELECT * FROM vec_table WHERE category = "document" -ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 5; ``` @@ -97,7 +97,7 @@ LIMIT 5; SELECT * FROM ( SELECT * FROM vec_table - ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') + ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 5 ) t WHERE category = "document"; @@ -113,7 +113,7 @@ WHERE category = "document"; -- 对于以下查询,`WHERE` 过滤条件在 KNN 之前执行,因此不能使用向量搜索索引: SELECT * FROM docs WHERE ver = "v2.0" -ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 5; ``` @@ -135,7 +135,7 @@ CREATE TABLE docs ( SELECT * FROM docs PARTITION (p_v2_0) -ORDER BY Vec_Cosine_distance(embedding, '[1, 2, 3]') +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 5; ``` @@ -181,7 +181,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; ```sql [tidb]> EXPLAIN SELECT * FROM vector_table_with_index -ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 10; +-----+-------------------------------------------------------------------------------------+ | ... | operator info | @@ -222,7 +222,7 @@ LIMIT 10; ```sql -- 使用了错误的距离函数: [tidb]> EXPLAIN SELECT * FROM vector_table_with_index -ORDER BY Vec_l2_Distance(embedding, '[1, 2, 3]') +ORDER BY VEC_L2_DISTANCE(embedding, '[1, 2, 3]') LIMIT 10; [tidb]> SHOW WARNINGS; @@ -230,7 +230,7 @@ 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 +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') DESC LIMIT 10; [tidb]> SHOW WARNINGS; @@ -243,7 +243,7 @@ ANN index not used: index can be used only when ordering by vec_cosine_distance( ```sql [tidb]> EXPLAIN ANALYZE SELECT * FROM vector_table_with_index -ORDER BY Vec_Cosine_Distance(embedding, '[1, 2, 3]') +ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 10; +-----+--------------------------------------------------------+-----+ | | execution info | | From c00b0fc6e6fcbb1a4982ad5d9938606cf8e80ae8 Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 10 Oct 2024 17:08:13 +0800 Subject: [PATCH 080/109] make "USING HNSW" as default --- vector-search-index.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 800d2899dc12..67cd406f7a1d 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -38,24 +38,27 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped ```sql CREATE TABLE foo ( id INT PRIMARY KEY, - data VECTOR(5), - VECTOR INDEX idx_data USING HNSW ((VEC_COSINE_DISTANCE(data))) + embedding VECTOR(5), + VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))) ); ``` - 对于现有的表,如果该表已包含向量列,可以通过以下语法为向量列创建 HNSW 索引: ```sql + CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))); + ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))); + + -- 你也可以显式指定使用 HNSW 构建向量搜索索引 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; ``` 在创建 HNSW 向量索引时,你需要指定向量的距离函数: -- 余弦距离:`((VEC_COSINE_DISTANCE(col_name))) USING HNSW` -- L2 距离:`((VEC_L2_DISTANCE(col_name))) USING HNSW` +- 余弦距离:`((VEC_COSINE_DISTANCE(embedding)))` +- L2 距离:`((VEC_L2_DISTANCE(embedding)))` 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 From 6d13accb050358f95365e3731a93254553bb39d7 Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 10 Oct 2024 17:11:41 +0800 Subject: [PATCH 081/109] Apply suggestions from code review --- vector-search-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index 67cd406f7a1d..af8d99a3006a 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -62,7 +62,7 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 -有关向量搜索索引的约束和限制,请参阅[向量搜索索引的约束](/vector-search-index.md#向量搜索索引的约束)。 +有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 ## 使用向量搜索索引 From 36d03f9737551b6fded3a8cf35bdc449c045c345 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Sat, 12 Oct 2024 14:51:03 +0800 Subject: [PATCH 082/109] Apply suggestions from code review Co-authored-by: JaySon --- vector-search-data-types.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index fc581f1eb072..5a55067cb50b 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -226,17 +226,10 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 如需了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 -### 向量与其他数据类型之间的转换 - -目前 TiDB 无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以使用字符串作为中间类型进行转换。 ## 使用限制 -- 向量最大支持 16383 维。 -- 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 目前,向量类型不能存储双精度浮点数。计划在未来的版本中支持这一功能。在此期间,如果为向量类型导入双精度浮点数,它们将被转换为单精度数。 - -有关其他限制,请参阅[向量搜索限制](/vector-search-limitations.md)。 +有关向量类型的限制,请参阅[向量搜索限制](/vector-search-limitations.md)以及[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 ## MySQL 兼容性 From e03d678b8bb0508180f7f31911258f88e671db7e Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 14 Oct 2024 15:51:06 +0800 Subject: [PATCH 083/109] format udpates --- vector-search-get-started-using-python.md | 6 +++--- vector-search-get-started-using-sql.md | 4 ++-- vector-search-integrate-with-jinaai-embedding.md | 6 +++--- vector-search-integrate-with-langchain.md | 6 +++--- vector-search-integrate-with-llamaindex.md | 6 +++--- vector-search-integrate-with-sqlalchemy.md | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index cabeebf12d68..35164af9c209 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -66,14 +66,14 @@ 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,`` 默认为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 以下为各参数的解释: -- ``:TiDB 集群的主机号。 -- ``:TiDB 集群的端口。 - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 +- ``:TiDB 集群的主机号。 +- ``:TiDB 集群的端口。 - ``:要连接的数据库名称。
diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index fe2010885e84..2eba719e343a 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -42,10 +42,10 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 在本地部署的集群启动后,在终端中执行你的集群连接命令: -以下为 MacOS 上的连接命令示例: +以下为 macOS 上的连接命令示例: ```bash - mysql --comments --host 127.0.0.1 --port 4000 -u root +mysql --comments --host 127.0.0.1 --port 4000 -u root ```
diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index c360a24ef7db..f920644e723a 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -70,14 +70,14 @@ export TIDB_DATABASE_URL="mysql+pymysql://:@:/` 默认为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 以下为各参数的解释: -- ``:TiDB 集群的主机地址。 -- ``:TiDB 集群的端口号。 - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 - ``:要连接的数据库名称。
diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index b87518db90d5..e45b2d730c06 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -91,14 +91,14 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/` 地址为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 以下为各参数的解释: -- ``:TiDB 集群的主机地址。 -- ``:TiDB 集群的端口号。 - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 - ``:要连接的数据库名称。
diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 27332841d6ff..b3a4457ac1d9 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -88,14 +88,14 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/` 地址为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 以下为各参数的解释: -- ``:TiDB 集群的主机地址。 -- ``:TiDB 集群的端口号。 - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 +- ``:TiDB 集群的主机地址。 +- ``:TiDB 集群的端口号。 - ``:要连接的数据库名称。
diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 5aae29e0c61e..1c8d50a8c78f 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -75,14 +75,14 @@ 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,`` 默认为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 以下为各参数的解释: -- ``:TiDB 集群的主机。 -- ``:TiDB 集群的端口。 - ``:连接 TiDB 集群的用户名。 - ``:连接 TiDB 集群的密码。 +- ``:TiDB 集群的主机。 +- ``:TiDB 集群的端口。 - ``:要连接的数据库名称。
From 30118d02ba5e46177cc91f33e07c847910f2df96 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 14 Oct 2024 16:34:42 +0800 Subject: [PATCH 084/109] =?UTF-8?q?remove=20"=E6=88=96=E5=88=A0=E9=99=A4"?= =?UTF-8?q?=20from=20the=20experimental=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vector-search-data-types.md | 2 +- vector-search-functions-and-operators.md | 2 +- vector-search-get-started-using-python.md | 2 +- vector-search-get-started-using-sql.md | 2 +- vector-search-improve-performance.md | 2 +- vector-search-index.md | 2 +- vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-jinaai-embedding.md | 2 +- vector-search-integrate-with-langchain.md | 2 +- vector-search-integrate-with-llamaindex.md | 2 +- vector-search-integrate-with-peewee.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- vector-search-integration-overview.md | 2 +- vector-search-limitations.md | 2 +- vector-search-overview.md | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index fc581f1eb072..7a90b3b59892 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -9,7 +9,7 @@ summary: 本文介绍 TiDB 的向量数据类型。 > **警告:** > -> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 目前支持的向量数据类型包括: diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 3add099d89e8..7babb5a0d848 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -9,7 +9,7 @@ summary: 本文介绍 TiDB 的向量相关函数和操作。 > **警告:** > -> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 该功能目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 向量函数 diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index cabeebf12d68..44ba6024ec0a 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -11,7 +11,7 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index fe2010885e84..614262ca11b3 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -16,7 +16,7 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 7c446085cb6d..5b8f4246826e 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -9,7 +9,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 为向量列添加向量搜索索引 diff --git a/vector-search-index.md b/vector-search-index.md index e3e8831a3552..2b1e662208e6 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -11,7 +11,7 @@ K 近邻(K-Nearest Neighbors,简称 KNN)搜索是一种在向量空间中 > **警告:** > -> 向量搜索索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world) 向量搜索索引算法。 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 8d9f54e41a02..f47482c0228c 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -9,7 +9,7 @@ summary: 了解如何在 Django ORM 中通过 TiDB 向量搜索功能存储向 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index c360a24ef7db..f7bb79c262d4 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -9,7 +9,7 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 TiDB 向量搜索, > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index b87518db90d5..69553785d7e1 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -9,7 +9,7 @@ summary: 展示如何在 LangChain 中使用 TiDB 向量搜索 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 > **Tip** > diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 27332841d6ff..2b647f7f275a 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -9,7 +9,7 @@ summary: 了解如何在 LlamaIndex 中使用 TiDB 向量搜索。 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 > **Tip** > diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 0d3adfadb957..bca712063d61 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -9,7 +9,7 @@ summary: 了解如何在 peewee 中通过 TiDB 向量搜索功能存储向量并 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 5aae29e0c61e..2c43715c76b5 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -9,7 +9,7 @@ summary: 了解如何在 SQLAlchemy 中通过 TiDB 向量搜索功能存储向 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 前置需求 diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index 4a4974f2d871..7fd219903831 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -9,7 +9,7 @@ summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## AI 框架 diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 4ced63014376..3b50ed1e9747 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -9,7 +9,7 @@ summary: 了解 TiDB 向量搜索功能的限制。 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 diff --git a/vector-search-overview.md b/vector-search-overview.md index 157dbcd53e17..e1f546f5ecc8 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -9,7 +9,7 @@ TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、 > **警告:** > -> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +> 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 ## 概念 From 54801233248cd4d11a1d2de046e92bd2efd0313b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 14 Oct 2024 17:07:42 +0800 Subject: [PATCH 085/109] update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-data-types.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 5ad7aac08aa6..ae811feaff8f 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -149,6 +149,9 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 类型转换 (Cast) +目前 TiDB 无法直接在向量和其他数据类型 (如 `JSON`) 之间进行转换,但你可以使用字符串作为中间数据类型进行转换。 + + ### 向量与字符串之间的转换 可以使用以下函数在向量和字符串之间进行转换: From 5e0c7d58a0110166a5433ab8cdde95b7dc01a319 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:11:23 +0800 Subject: [PATCH 086/109] Apply suggestions from code review Co-authored-by: Grace Cai --- vector-search-improve-performance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 5b8f4246826e..0b61f5e5fc25 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -35,6 +35,6 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 预热索引 -当访问一个从未被使用过或长时间未被使用过的索引(冷访问)时,TiDB 需要从 S3 或磁盘(而不是内存)加载整个索引。这个过程需要一定的时间,往往会导致较高的查询延迟。此外,如果集群长时间(比如数小时)内没有进行 SQL 查询,计算资源就会被回收,这样下次访问时就会变成冷访问。 +当访问一个从未被使用过或长时间未被使用过的索引(冷访问)时,TiDB 需要从云存储或磁盘(而不是内存)加载整个索引。这个过程需要一定的时间,往往会导致较高的查询延迟。此外,如果集群长时间(比如数小时)内没有进行 SQL 查询,计算资源就会被回收,这样下次访问时就会变成冷访问。 要避免这种查询延迟,可在实际工作负载前,使用类似的向量搜索查询对索引进行预热。 \ No newline at end of file From 18a286bfb6e4784f556bbc12a82c94e1c982ddd1 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:17:38 +0800 Subject: [PATCH 087/109] Apply suggestions from code review Co-authored-by: JaySon --- vector-search-limitations.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 3051f1035d2f..62afe741990d 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -17,7 +17,8 @@ summary: 了解 TiDB 向量搜索功能的限制。 - 向量列不能作为唯一索引或者唯一索引的一部分 - 向量列不能作为分区键或者分区键的一部分 - 创建[向量搜索索引](/vector-search-index.md)时的限制,参照[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 -- 向量数据类型不支持存储双精度浮点数(该功能计划在未来的版本中支持)。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 +- 向量数据类型不支持存储双精度浮点数。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 +- 目前 TiDB 不支持将向量类型的列修改为其他数据类型(如 `JSON`、`VARCHAR` 等)。 - 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 - DM 不支持 MySQL 9.0 的向量数据类型同步。 - CDC 对于不支持向量数据的下游会修改数据类型。参照[向量搜索功能兼容性说明](/ticdc/ticdc-compatibility.md#向量搜索功能兼容性说明实验特性) From 97d997e5c9a15d3888aac7d57d1583c149af361f Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Tue, 15 Oct 2024 15:15:00 +0800 Subject: [PATCH 088/109] =?UTF-8?q?add=20"Cast=20between=20Vector=20?= =?UTF-8?q?=E2=87=94=20other=20data=20types"=20back?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vector-search-data-types.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index ae811feaff8f..38f23155d430 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -149,9 +149,6 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 类型转换 (Cast) -目前 TiDB 无法直接在向量和其他数据类型 (如 `JSON`) 之间进行转换,但你可以使用字符串作为中间数据类型进行转换。 - - ### 向量与字符串之间的转换 可以使用以下函数在向量和字符串之间进行转换: @@ -229,6 +226,11 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 如需了解其他转换函数,请参阅[向量函数和操作符](/vector-search-functions-and-operators.md)。 +### 向量与其他数据类型之间的转换 + +目前 TiDB 无法直接在向量和其他数据类型(如 `JSON`)之间进行转换,但你可以在执行的 SQL 语句中使用字符串作为中间类型进行转换。 + +需要注意的是,对于存储在表中的向量数据类型列,无法通过 `ALTER TABLE ... MODIFY COLUMN ...` 转换为其他数据类型。 ## 使用限制 From a93a7d23e4dc2ae6b9108a4d0c9376adf5287a31 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:07:05 +0800 Subject: [PATCH 089/109] Apply suggestions from code review Co-authored-by: Grace Cai --- br/backup-and-restore-overview.md | 2 +- tiflash/tiflash-configuration.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/br/backup-and-restore-overview.md b/br/backup-and-restore-overview.md index f328f33033c9..4facc4de6482 100644 --- a/br/backup-and-restore-overview.md +++ b/br/backup-and-restore-overview.md @@ -120,7 +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 集群。 | +| 向量搜索 | | 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有[向量数据类型](/vector-search-data-types.md)的表恢复至 v8.4.0 之前的 TiDB 集群。 | ### 版本间兼容性 diff --git a/tiflash/tiflash-configuration.md b/tiflash/tiflash-configuration.md index f4e4e624426f..9b9f8bdf05c7 100644 --- a/tiflash/tiflash-configuration.md +++ b/tiflash/tiflash-configuration.md @@ -68,8 +68,8 @@ delta_index_cache_size = 0 ## DTFile 储存文件格式 ## * format_version = 2 v6.0.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 = 4 v6.2.0 ~ v7.3.0 的默认文件格式,优化了写放大问题,同时减少了后台线程消耗。 + ## * format_version = 5 v7.4.0 ~ v8.3.0 的默认文件格式(从 v7.3.0 开始引入),该格式可以合并小文件从而减少了物理文件数量。 ## * format_version = 6 从 v8.4.0 开始引入,部分支持了向量索引的构建与存储。 ## * format_version = 7 v8.4.0 及以后版本的默认文件格式 (从 v8.4.0 开始引入),该格式用于支持向量索引的构建与存储。 # format_version = 7 From dd389230486d579dd22e868b6e187f66cdecb070 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 16 Oct 2024 10:59:29 +0800 Subject: [PATCH 090/109] refine descriptions in vector-search-limitations --- vector-search-limitations.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/vector-search-limitations.md b/vector-search-limitations.md index 62afe741990d..d081c0069be5 100644 --- a/vector-search-limitations.md +++ b/vector-search-limitations.md @@ -11,17 +11,25 @@ summary: 了解 TiDB 向量搜索功能的限制。 > > 向量搜索目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。 +## 向量数据类型限制 + - 向量最大支持 16383 维。 - 向量数据中不支持 `NaN`、`Infinity` 和 `-Infinity` 浮点数。 -- 向量列不能作为主键或者主键的一部分 -- 向量列不能作为唯一索引或者唯一索引的一部分 -- 向量列不能作为分区键或者分区键的一部分 -- 创建[向量搜索索引](/vector-search-index.md)时的限制,参照[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 +- 向量列不能作为主键或者主键的一部分。 +- 向量列不能作为唯一索引或者唯一索引的一部分。 +- 向量列不能作为分区键或者分区键的一部分。 - 向量数据类型不支持存储双精度浮点数。当向 TiDB 中的向量列插入或存储双精度浮点数时,TiDB 会将这些双精度浮点数自动转换为单精度浮点数。 - 目前 TiDB 不支持将向量类型的列修改为其他数据类型(如 `JSON`、`VARCHAR` 等)。 -- 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的恢复至 v8.4.0 之前的 TiDB 集群。 -- DM 不支持 MySQL 9.0 的向量数据类型同步。 -- CDC 对于不支持向量数据的下游会修改数据类型。参照[向量搜索功能兼容性说明](/ticdc/ticdc-compatibility.md#向量搜索功能兼容性说明实验特性) + +## 向量搜索索引限制 + +参考[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 + +## 工具兼容性 + +- 确保使用 BR v8.4.0 及以上版本进行备份与恢复。不支持将带有向量数据类型的表恢复至 v8.4.0 之前的 TiDB 集群。 +- TiDB Data Migration (DM) 不支持迁移或同步 MySQL 9.0 的向量数据类型到 TiDB。 +- TiCDC 在同步向量数据到不支持向量数据类型的下游时会修改数据类型。详情参考[向量数据类型兼容性说明](/ticdc/ticdc-compatibility.md#向量数据类型兼容性说明)。 ## 反馈 From 6243bd060c8202f12613aea8351dd240919f6be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Wed, 16 Oct 2024 12:03:47 +0800 Subject: [PATCH 091/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 53 ++++++++---------------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index b2ddab6cc371..8104748cbcd9 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -63,6 +63,9 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 +> **注意:** +> +> 在创建表时声明向量搜索索引时,TiDB 会自动为该表设置 TiFlash 副本数为 1。若建表时未声明,后续为表新增向量搜索索引时,需要手动为表创建 TiFlash 副本,例如:`ALTER TABLE 'table_name' SET TIFLASH REPLICA 1;` ## 使用向量搜索索引 @@ -108,56 +111,20 @@ 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)。 - ## 查看索引构建进度 -与其他索引不同,向量搜索索引是通过异步方式构建的。这意味着,在完成大批量数据插入后,向量索引可能不会立即构建完成以供查询使用,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 +在大批量数据插入后,部分数据可能会处于 delta 层等待后续的持久化。对于已经持久化后的向量数据,向量搜索索引的构建是通过同步的方式构建的,处于 delta 层的数据会在完成持久化再开始构建,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 要查看索引构建进度,可以按如下方式查询 `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 | -+---------------+------------+----------------+----------+--------------------+-------------+-----------+------------+---------------------+-------------------------+--------------------+------------------------+------------------+ ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ +| TIDB_DATABASE | TIDB_TABLE | TABLE_ID | COLUMN_NAME | INDEX_NAME | COLUMN_ID | INDEX_ID | INDEX_KIND | ROWS_STABLE_INDEXED | ROWS_STABLE_NOT_INDEXED | ROWS_DELTA_INDEXED | ROWS_DELTA_NOT_INDEXED | ERROR_MESSAGE | TIFLASH_INSTANCE | ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ +| test | tcff1d827 | 219 | col1fff | 0a452311 | 7 | 1 | HNSW | 29646 | 0 | 0 | 0 | | 127.0.0.1:3930 | +| test | foo | 717 | embedding | idx_embedding | 2 | 1 | HNSW | 0 | 0 | 0 | 3 | | 127.0.0.1:3930 | ++---------------+------------+----------+-------------+---------------+-----------+----------+------------+---------------------+-------------------------+--------------------+------------------------+---------------+------------------+ ``` - 可以通过 `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列查看索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,表示索引构建完成。 From 52e696f9e683a7af493009fb08cf12f95bdf17f8 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 16 Oct 2024 14:44:10 +0800 Subject: [PATCH 092/109] vector-search-index: refine new changes --- vector-search-index.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 8104748cbcd9..232ccc93a170 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -48,12 +48,18 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped ```sql CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))); ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))); - + -- 你也可以显式指定使用 HNSW 构建向量搜索索引 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; ``` +> **注意:** +> +> 向量搜索索引功能的实现需要基于表的 TiFlash 副本。 +> +> - 在建表时如果定义了向量搜索索引,TiDB 将自动为该表创建一个 TiFlash 副本。 +> - 如果建表时未定义向量搜索索引,并且该表当前没有 TiFlash 副本,那么为该表添加向量搜索索引时,你需要先手动为该表创建 TiFlash 副本,例如:`ALTER TABLE 'table_name' SET TIFLASH REPLICA 1;`。 在创建 HNSW 向量索引时,你需要指定向量的距离函数: @@ -63,9 +69,6 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 -> **注意:** -> -> 在创建表时声明向量搜索索引时,TiDB 会自动为该表设置 TiFlash 副本数为 1。若建表时未声明,后续为表新增向量搜索索引时,需要手动为表创建 TiFlash 副本,例如:`ALTER TABLE 'table_name' SET TIFLASH REPLICA 1;` ## 使用向量搜索索引 @@ -113,7 +116,7 @@ WHERE category = "document"; ## 查看索引构建进度 -在大批量数据插入后,部分数据可能会处于 delta 层等待后续的持久化。对于已经持久化后的向量数据,向量搜索索引的构建是通过同步的方式构建的,处于 delta 层的数据会在完成持久化再开始构建,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 +当插入大批量数据后,部分数据可能没有立即持久化到 TiFlash 中。对于已经持久化的向量数据,向量搜索索引是通过同步的方式构建的;对于尚未未持久化的数据,向量搜索索引会在数据持久化后才开始构建,但这并不会影响数据的准确性和一致性。你仍然可以随时进行向量搜索,并获得完整的结果,但需要注意的是,查询性能只有在向量搜索索引完全构建好之后才会达到最佳水平。 要查看索引构建进度,可以按如下方式查询 `INFORMATION_SCHEMA.TIFLASH_INDEXES` 表: @@ -131,9 +134,9 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 作为参考,对于一个 500 MiB 的向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 -- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到稳定层。这个合并过程称为“压缩”。 +- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。TiFlash 存储层的数据主要存放在 Delta 层和 Stable 层。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到稳定层。这个合并过程称为“压缩”。 - Delta 层本身是不包含索引的。为了达到最佳性能,你可以强制将 Delta 层合并到稳定层,以确保所有的数据都能够被索引: + Delta 层本身是不包含索引的。为了达到最佳性能,你可以强制将 Delta 层合并到 Stable 层,以确保所有的数据都能够被索引: ```sql ALTER TABLE COMPACT; From bf3511698ef30fa22696714ca81ff9d9f6b8e016 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 16 Oct 2024 17:20:59 +0800 Subject: [PATCH 093/109] Apply suggestions from code review Co-authored-by: Aolin --- vector-search-data-types.md | 25 +++++++++++----------- vector-search-get-started-using-python.md | 15 +++++++------ vector-search-get-started-using-sql.md | 17 ++++++++------- vector-search-improve-performance.md | 4 ++-- vector-search-integrate-with-django-orm.md | 6 +++--- vector-search-integrate-with-peewee.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- 7 files changed, 36 insertions(+), 35 deletions(-) diff --git a/vector-search-data-types.md b/vector-search-data-types.md index 38f23155d430..d5fe04584d9b 100644 --- a/vector-search-data-types.md +++ b/vector-search-data-types.md @@ -13,8 +13,8 @@ summary: 本文介绍 TiDB 的向量数据类型。 目前支持的向量数据类型包括: -- `VECTOR`: 存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。 -- `VECTOR(D)`: 存储一组单精度浮点数 (Float) 向量,向量维度固定为 `D`。 +- `VECTOR`:存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。 +- `VECTOR(D)`:存储一组单精度浮点数 (Float) 向量,向量维度固定为 `D`。 与使用 [`JSON`](/data-type-json.md) 类型相比,使用向量类型具有以下优势: @@ -43,23 +43,23 @@ INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); INSERT INTO vector_table VALUES (2, NULL); ``` -当将不符合语法的字符串作为向量数据插入时,TiDB 会进行报错: +插入不符合语法的字符串作为向量数据时,TiDB 会报错: ```sql [tidb]> INSERT INTO vector_table VALUES (3, '[5, ]'); ERROR 1105 (HY000): Invalid vector text: [5, ] ``` -下面的示例中 `embedding` 向量列的维度在建表时已经定义为 `3`,因此当插入其他维度的向量数据时,TiDB 会进行报错: +下面的示例中 `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-functions-and-operators.md)。 -可参阅[向量搜索索引](/vector-search-index.md)了解向量搜索索引的信息。 +关于向量搜索索引的更多信息,可参阅[向量搜索索引](/vector-search-index.md)。 ## 混合存储不同维度的向量 @@ -79,7 +79,7 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 插入一个 2 维 ## 比较 -[比较运算符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符) 如 `=`, `!=`, `<`, `>`, `<=` 和 `>=` 等都能正常对向量数据进行比较。可参阅[向量函数与操作符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符)了解向量数据类型支持的所有函数和操作符。 +向量数据支持[比较运算符](/vector-search-functions-and-operators.md#扩展的内置函数和运算符),例如 `=`、`!=`、`<`、`>`、`<=` 和 `>=` 等。关于向量数据类型支持的所有函数和操作符,可参阅[向量函数与操作符](/vector-search-functions-and-operators.md)。 比较向量数据类型时,TiDB 会以向量中的各个元素为单位进行依次比较,如: @@ -92,11 +92,10 @@ INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 插入一个 2 维 - 两个向量中的各个元素逐一进行数值比较。 - 当遇到第一个不同的元素时,它们之间的数值比较结果即为两个向量之间的比较结果。 -- 如果一个向量是另一个向量的前缀,那么维度小的向量 _小于_ 维度大的向量。例如,`[1,2,3] < [1,2,3,0]`。 -- 长度相同且各个元素相同的两个向量 _相等_ 。 -- 空向量 _小于_ 任何非空向量。例如,`[] < [1]`。 -- 两个空向量 _相等_ 。 - +- 如果一个向量是另一个向量的前缀,那么维度小的向量**小于**维度大的向量。例如,`[1,2,3] < [1,2,3,0]`。 +- 长度相同且各个元素相同的两个向量**相等**。 +- 空向量**小于**任何非空向量。例如,`[] < [1]`。 +- 两个空向量**相等**。 在进行向量比较时,请使用[显式转换](#类型转换-cast)将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较: @@ -234,7 +233,7 @@ ERROR 1105 (HY000): vectors have different dimensions: 1 and 3 ## 使用限制 -有关向量类型的限制,请参阅[向量搜索限制](/vector-search-limitations.md)以及[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 +有关向量类型的限制,请参阅[向量搜索限制](/vector-search-limitations.md)以及[向量搜索索引的使用限制](/vector-search-index.md#使用限制)。 ## MySQL 兼容性 diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index ebc4e89e8b62..d4eed13b0c9a 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -7,7 +7,7 @@ summary: 了解如何使用 Python 和 TiDB 向量搜索快速开发可执行语 本文将展示如何开发一个简单的 AI 应用,这个 AI 应用实现了简单的**语义搜索**功能。不同于传统的关键字搜索,语义搜索可以智能地理解你的输入,返回更相关的结果。例如,在“狗”、“鱼”和“树”这三条内容中搜索“一种会游泳的动物”时,语义搜索会将“鱼”作为最相关的结果返回。 -在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector SDK for Python](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型完成这个 AI 应用的开发。 +在本文中,你将使用 [TiDB 向量搜索](/vector-search-overview.md)、Python、[TiDB Vector Python SDK](https://github.com/pingcap/tidb-vector-python) 和 AI 大模型完成这个 AI 应用的开发。 > **警告:** > @@ -49,7 +49,7 @@ pip install sqlalchemy pymysql sentence-transformers tidb-vector python-dotenv ``` - `tidb-vector`:用于与 TiDB 向量搜索交互的 Python 客户端。 -- [`sentence-transformers`](https://sbert.net): 一个提供预训练模型的 Python 库,用于从文本生成[向量嵌入](/vector-search-overview.md#向量嵌入)。 +- [`sentence-transformers`](https://sbert.net):提供预训练模型的 Python 库,用于从文本生成[向量嵌入](/vector-search-overview.md#向量嵌入)。 ### 第 3 步:配置 TiDB 集群的连接字符串 @@ -105,7 +105,7 @@ TIDB_DATABASE_URL="mysql+pymysql://:@:/" 5. 在 Python 项目的根目录下新建一个 `.env` 文件,将连接字符串粘贴到其中。 - 以下为 MacOS 的示例: + 以下为 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" @@ -140,7 +140,7 @@ def text_to_embedding(text): > **Note** > -> 请确保你创建的表中向量列的维度与嵌入模型生成的向量维度一致。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度, `embedded_documents` 的向量列维度也应为 384。 +> 请确保你创建的表中向量列的维度与嵌入模型生成的向量维度一致。例如,**msmarco-MiniLM-L12-cos-v5** 模型生成的向量有 384 个维度,`embedded_documents` 的向量列维度也应为 384。 ```python import os @@ -198,7 +198,7 @@ vector_store.insert( ### 第 7 步:执行语义搜索 -查询一个与 `documents` 中的任何单词都不匹配的关键词,比如 "a swimming animal"。 +查询一个与已有文档 `documents` 中任何单词都不匹配的关键词,比如 "a swimming animal"。 以下的代码会再次使用 `text_to_embedding()` 函数将查询文本转换为向量嵌入,然后使用该嵌入进行查询,找出最匹配的前三个词。 @@ -223,10 +223,11 @@ Search result ("a swimming animal"): - text: "tree", distance: 0.798545178640937 ``` -搜索结果中的 3 个词会按向量的远近排列:距离越小,对应的 `document` 越相关。 +搜索结果中的三个词按它们与查询向量的距离排序:距离越小,对应的 `document` 越相关。 因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 ## 另请参阅 -- [Vector Data Types](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.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 index df9c9dfddb38..05f901bf8648 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -74,17 +74,17 @@ mysql --comments --host 127.0.0.1 --port 4000 -u root ### 第 2 步:创建向量表 -在建表时,你可以使用 `VECTOR` 数据类型声明指定列为[向量](/vector-search-overview.md#向量嵌入)列。 +创建表时,你可以使用 `VECTOR` 数据类型声明指定列为[向量](/vector-search-overview.md#向量嵌入)列。 -例如,如需创建一张带有三维 `VECTOR` 列的 `embedded_documents` 表,可以在 MySQL CLI 中执行以下 SQL 语句: +例如,要创建一个带有三维 `VECTOR` 列的 `embedded_documents` 表,可以使用 MySQL CLI 执行以下 SQL 语句: ```sql USE test; CREATE TABLE embedded_documents ( id INT PRIMARY KEY, - -- document 列存储 document 的原始内容 + -- document 列存储文档的原始内容 document TEXT, - -- embedding 列存储 document 的向量表示 + -- embedding 列存储文档的向量表示 embedding VECTOR(3) ); ``` @@ -143,11 +143,11 @@ SELECT * FROM embedded_documents; ### 第 5 步:执行向量搜索查询 -与全文搜索类似,在使用向量搜索时,你需要指定搜索词。 +与全文搜索类似,在使用向量搜索时,你需要提供搜索词。 在本例中,搜索词是“一种会游泳的动物”,假设其对应的向量是 `[1,2,3]`。在实际应用中,你需要使用[嵌入模型](/vector-search-overview.md#嵌入模型)将用户的搜索词转换为向量。 -执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量(余弦距离最小)的前三个向量。 +执行以下 SQL 语句后,TiDB 会计算 `[1,2,3]` 与表中各向量之间的余弦距离 (`vec_cosine_distance`),然后对这些距离进行排序并输出表中最接近搜索向量(余弦距离最小)的前三个文档。 ```sql SELECT id, document, vec_cosine_distance(embedding, '[1,2,3]') AS distance @@ -169,10 +169,11 @@ LIMIT 3; 3 rows in set (0.15 sec) ``` -搜索结果中的 3 个词会按向量的距离排列:距离越小,对应的 `document` 越相关。 +搜索结果中的三个词按它们与查询向量的距离排序:距离越小,对应的 `document` 越相关。 因此,从输出结果来看,会游泳的动物很可能是一条鱼 (`fish`),或者是一只有游泳天赋的狗 (`dog`)。 ## 另请参阅 -- [向量数据类型](/vector-search-data-types.md) \ No newline at end of file +- [向量数据类型](/vector-search-data-types.md) +- [向量搜索索引](/vector-search-index.md) \ No newline at end of file diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 0b61f5e5fc25..d09a20bee892 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -5,7 +5,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 # 优化向量搜索性能 -在 TiDB 中,你可以通过向量搜索功能进行近似近邻(Approximate Nearest Neighbor,简称 ANN)搜索,查找与给定的图像、文档等相似的结果。为了提升查询性能,请参考以下最佳实践。 +在 TiDB 中,你可以通过向量搜索功能进行近似最近邻(Approximate Nearest Neighbor,简称 ANN)搜索,查找与给定的图像、文档等相似的结果。为了提升查询性能,请参考以下最佳实践。 > **警告:** > @@ -17,7 +17,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 确保向量索引已完全构建 -向量搜索索引是通过异步方式构建的。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#view-index-build-progress)。 +向量搜索索引是通过异步方式构建的。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#查看索引构建进度)。 ## 减少向量维数或缩短嵌入时间 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index f47482c0228c..9d945b5c7f41 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -66,7 +66,7 @@ pip install Django django-tidb mysqlclient numpy python-dotenv `django-tidb` 是一个为 Django 提供的 TiDB 适配器。通过该适配器,Django ORM 实现了对 TiDB 特有的功能(如,向量搜索)的支持,并解决了 TiDB 和 Django 之间的兼容性问题。 -安装 `django-tidb` 时,请选择与你的 Django 版本相匹配的版本。例如,如果你使用的是 `django==4.2.*`, 则应安装 `django-tidb===4.2.*`,其中 minor 版本号不需要完全相同。建议使用最新的 minor 版本。 +安装 `django-tidb` 时,选择与你的 Django 版本匹配的版本。例如,如果你使用的是 `django==4.2.*`,则应安装 `django-tidb==4.2.*`,其中 minor 版本号不需要完全相同。建议使用最新的 minor 版本。 更多信息,请参考 [django-tidb 仓库](https://github.com/pingcap/django-tidb)。 @@ -134,7 +134,7 @@ TIDB_DATABASE=test - `TIDB_DATABASE`:要连接的数据库名称。 - `TIDB_CA_PATH`:根证书文件的路径。 - 以下为 MacOS 的示例: + 以下为 macOS 的示例: ```dotenv TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com @@ -213,7 +213,7 @@ if TIDB_CA_PATH: `tidb-django` 提供了一个 `VectorField`,可以在表中用来表示和存储向量类型。 -创建一个表格,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 +创建一个表,其中包含一个向量数据类型的 `embedding` 列,用于存储三维向量。 ```python class Document(models.Model): diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index bca712063d61..2fef41534540 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -124,7 +124,7 @@ TIDB_DATABASE=test - `TIDB_DATABASE`:要连接的数据库名称。 - `TIDB_CA_PATH`:根证书文件的路径。 - 以下为 MacOS 的示例: + 以下为 macOS 的示例: ```dotenv TIDB_HOST=gateway01.****.prod.aws.tidbcloud.com diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index 9bcfdb016cac..a5c4c21370f5 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -114,7 +114,7 @@ TIDB_DATABASE_URL=mysql+pymysql://:@:/ 5. 在 Python 项目的根目录下新建一个 `.env` 文件,并将连接字符串粘贴到其中。 - 以下为 MacOS 的示例: + 以下为 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" From 6fa2321c4e3ab12d8af2b879591bcd73020a0b8f Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 16 Oct 2024 19:22:07 +0800 Subject: [PATCH 094/109] fix a broken link --- vector-search-integrate-with-llamaindex.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index eed2ca5f3de2..0531288bc23e 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -311,5 +311,5 @@ Empty Response ## 另请参阅 -- [向量数据类型](/tidb-cloud/vector-search-data-types.md) +- [向量数据类型](/vector-search-data-types.md) - [向量搜索索引](/vector-search-index.md) \ No newline at end of file From a13da5fa493cbc9b9b768b354b9e2eaea177101c Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Thu, 17 Oct 2024 10:02:18 +0800 Subject: [PATCH 095/109] fix broken links --- vector-search-get-started-using-python.md | 2 +- vector-search-get-started-using-sql.md | 2 +- vector-search-integrate-with-django-orm.md | 2 +- vector-search-integrate-with-jinaai-embedding.md | 2 +- vector-search-integrate-with-langchain.md | 2 +- vector-search-integrate-with-llamaindex.md | 2 +- vector-search-integrate-with-peewee.md | 2 +- vector-search-integrate-with-sqlalchemy.md | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vector-search-get-started-using-python.md b/vector-search-get-started-using-python.md index d4eed13b0c9a..a29a0f2c8c02 100644 --- a/vector-search-get-started-using-python.md +++ b/vector-search-get-started-using-python.md @@ -24,7 +24,7 @@ summary: 了解如何使用 Python 和 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 diff --git a/vector-search-get-started-using-sql.md b/vector-search-get-started-using-sql.md index 05f901bf8648..d79a5d7e32ad 100644 --- a/vector-search-get-started-using-sql.md +++ b/vector-search-get-started-using-sql.md @@ -28,7 +28,7 @@ TiDB 扩展了 MySQL 语法以支持[向量搜索](/vector-search-overview.md) 如果你还没有 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md index 9d945b5c7f41..6f6d262a43f9 100644 --- a/vector-search-integrate-with-django-orm.md +++ b/vector-search-integrate-with-django-orm.md @@ -22,7 +22,7 @@ summary: 了解如何在 Django ORM 中通过 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 diff --git a/vector-search-integrate-with-jinaai-embedding.md b/vector-search-integrate-with-jinaai-embedding.md index 7153fff9415a..ddc26e79bcf7 100644 --- a/vector-search-integrate-with-jinaai-embedding.md +++ b/vector-search-integrate-with-jinaai-embedding.md @@ -22,7 +22,7 @@ summary: 了解如何结合 Jina AI 嵌入模型 API 使用 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index 7c17d0be0172..b3ecd4e6480a 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -27,7 +27,7 @@ summary: 展示如何在 LangChain 中使用 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 0531288bc23e..6cfb2ceeec0a 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -27,7 +27,7 @@ summary: 了解如何在 LlamaIndex 中使用 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 快速开始 diff --git a/vector-search-integrate-with-peewee.md b/vector-search-integrate-with-peewee.md index 2fef41534540..064d951dd222 100644 --- a/vector-search-integrate-with-peewee.md +++ b/vector-search-integrate-with-peewee.md @@ -22,7 +22,7 @@ summary: 了解如何在 peewee 中通过 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 diff --git a/vector-search-integrate-with-sqlalchemy.md b/vector-search-integrate-with-sqlalchemy.md index a5c4c21370f5..6f25678c9c98 100644 --- a/vector-search-integrate-with-sqlalchemy.md +++ b/vector-search-integrate-with-sqlalchemy.md @@ -22,7 +22,7 @@ summary: 了解如何在 SQLAlchemy 中通过 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 Cloud Serverless 集群](/develop/dev-guide-build-cluster-in-cloud.md#第-1-步创建-tidb-cloud-serverless-集群),创建 TiDB Cloud 集群。 ## 运行示例应用程序 From f87d77155917f8593941829f9d311e0e93965782 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:38:29 +0800 Subject: [PATCH 096/109] Apply suggestions from code review Co-authored-by: Aolin Co-authored-by: Grace Cai --- vector-search-improve-performance.md | 2 +- vector-search-integrate-with-llamaindex.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index d09a20bee892..0a9ca5363d68 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -21,7 +21,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 减少向量维数或缩短嵌入时间 -随着向量维度大小的增加,向量搜索索引和查询的计算复杂度会显著增加,因为这意味着要进行更多的浮点数比较运算。 +随着向量维度增加,向量搜索索引和查询的计算复杂度会显著增加,因为需要进行更多的浮点数比较运算。 为了优化性能,可以考虑尽可能地减少向量的维数。这通常需要切换到另一种嵌入模型。在切换模型时,你需要评估改变嵌入模型对向量查询准确性的影响。 diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 6cfb2ceeec0a..321b08013786 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -215,7 +215,7 @@ 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, From 960218c59eb946804bfa0ace5ff5e94ffdd9ef99 Mon Sep 17 00:00:00 2001 From: JaySon Date: Thu, 17 Oct 2024 14:31:18 +0800 Subject: [PATCH 097/109] fix index naming --- vector-search-index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 232ccc93a170..bd7512c659d7 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -50,8 +50,8 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))); -- 你也可以显式指定使用 HNSW 构建向量搜索索引 - 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; + CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; + ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; ``` > **注意:** From 8b3f47623ec622fc54997f6e23ef8a86f003a8b5 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:07:27 +0800 Subject: [PATCH 098/109] Apply suggestions from code review Co-authored-by: Aolin Co-authored-by: Grace Cai Co-authored-by: JaySon --- TOC.md | 4 ++-- vector-search-index.md | 4 +--- vector-search-integrate-with-llamaindex.md | 2 ++ vector-search-overview.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/TOC.md b/TOC.md index 2a21e26b8489..1014d0004c2a 100644 --- a/TOC.md +++ b/TOC.md @@ -92,8 +92,8 @@ - ORM 库 - [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) - [peewee](/vector-search-integrate-with-peewee.md) - - [Django ORM](/vector-search-integrate-with-django-orm.md) - - [提升搜索性能](/vector-search-improve-performance.md) + - [Django](/vector-search-integrate-with-django-orm.md) + - [优化搜索性能](/vector-search-improve-performance.md) - [使用限制](/vector-search-limitations.md) - 事务 - [概览](/develop/dev-guide-transaction-overview.md) diff --git a/vector-search-index.md b/vector-search-index.md index bd7512c659d7..1b2852dfe72b 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -96,9 +96,7 @@ ORDER BY VEC_COSINE_DISTANCE(embedding, '[1, 2, 3]') LIMIT 5; ``` -如需使用带过滤条件的向量搜索索引,可以采用以下几种方法: - -**向量搜索后再过滤:** 先查询 K 个最近的邻居,再过滤掉不需要的结果: +如需使用带过滤条件的向量搜索索引,可以先通过向量搜索查询 K 个最近的邻居,再过滤掉不需要的结果: ```sql -- 对于以下查询,过滤条件是在 KNN 之后执行的,因此可以使用向量索引: diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index 321b08013786..eeb9ac5ad701 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -62,6 +62,8 @@ from llama_index.vector_stores.tidbvector import TiDBVectorStore ### 第 3 步:配置环境变量 +根据 TiDB 集群的部署方式不同,选择对应的环境变量配置方式。 +
diff --git a/vector-search-overview.md b/vector-search-overview.md index e1f546f5ecc8..ceaee390f46c 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -27,7 +27,7 @@ TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、 向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 -TiDB 专门引入了[向量数据类型](/vector-search-data-types.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 +TiDB 专门引入了[向量数据类型](/vector-search-data-types.md)以及[向量搜索索引](/vector-search-index),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 ### 嵌入模型 From 7ace7dea3e1f69056e4af4664edcad44382b201b Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:12:36 +0800 Subject: [PATCH 099/109] Update vector-search-improve-performance.md --- vector-search-improve-performance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 0a9ca5363d68..9d41ef6f0465 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -17,7 +17,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 确保向量索引已完全构建 -向量搜索索引是通过异步方式构建的。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#查看索引构建进度)。 +当插入大量的向量数据时,可能会有部分数据处于 delta 层等待后续的持久化,这一部分的数据会在完成持久化后为其构建向量索引。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#查看索引构建进度)。 ## 减少向量维数或缩短嵌入时间 From a3cd4e81e02db42a5b8e9c6ee0cb26483f476ae4 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:36:00 +0800 Subject: [PATCH 100/109] Apply suggestions from code review Co-authored-by: xixirangrang --- vector-search-index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 1b2852dfe72b..6f6cd571b800 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -49,7 +49,7 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))); ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))); - -- 你也可以显式指定使用 HNSW 构建向量搜索索引 + -- 你也可以显式指定 "USING HNSW" 使用 HNSW 构建向量搜索索引 CREATE VECTOR INDEX idx_embedding ON foo ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; ALTER TABLE foo ADD VECTOR INDEX idx_embedding ((VEC_COSINE_DISTANCE(embedding))) USING HNSW; ``` @@ -68,7 +68,7 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 -有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](/vector-search-index.md#使用限制)。 +有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](#使用限制)。 ## 使用向量搜索索引 @@ -132,7 +132,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; 作为参考,对于一个 500 MiB 的向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 -- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。TiFlash 存储层的数据主要存放在 Delta 层和 Stable 层。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到稳定层。这个合并过程称为“压缩”。 +- 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。TiFlash 存储层的数据主要存放在 Delta 层和 Stable 层。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到 Stable 层。这个合并过程称为“压缩”。 Delta 层本身是不包含索引的。为了达到最佳性能,你可以强制将 Delta 层合并到 Stable 层,以确保所有的数据都能够被索引: From 9aa03cd0832dc9deeb6420a02a69e297a4b3cb1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Fri, 18 Oct 2024 11:39:01 +0800 Subject: [PATCH 101/109] remove ORM operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-integrate-with-django-orm.md | 262 --------------------- vector-search-integrate-with-peewee.md | 254 -------------------- vector-search-integrate-with-sqlalchemy.md | 222 ----------------- 3 files changed, 738 deletions(-) delete mode 100644 vector-search-integrate-with-django-orm.md delete mode 100644 vector-search-integrate-with-peewee.md delete mode 100644 vector-search-integrate-with-sqlalchemy.md diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md deleted file mode 100644 index 6f6d262a43f9..000000000000 --- a/vector-search-integrate-with-django-orm.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -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-cloud-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-peewee.md b/vector-search-integrate-with-peewee.md deleted file mode 100644 index 064d951dd222..000000000000 --- a/vector-search-integrate-with-peewee.md +++ /dev/null @@ -1,254 +0,0 @@ ---- -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-cloud-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 deleted file mode 100644 index 6f25678c9c98..000000000000 --- a/vector-search-integrate-with-sqlalchemy.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -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-cloud-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,`` 默认为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 - -以下为各参数的解释: - -- ``:连接 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 From b8a100a82c1af309b9a34f23ac8caa3663f53486 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:57:56 +0800 Subject: [PATCH 102/109] remove part of ORM intro --- TOC.md | 4 --- vector-search-integration-overview.md | 40 ++------------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/TOC.md b/TOC.md index 1014d0004c2a..5587c52c958a 100644 --- a/TOC.md +++ b/TOC.md @@ -89,10 +89,6 @@ - [Langchain](/vector-search-integrate-with-langchain.md) - 嵌入模型/服务 - [Jina AI](/vector-search-integrate-with-jinaai-embedding.md) - - ORM 库 - - [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) - - [peewee](/vector-search-integrate-with-peewee.md) - - [Django](/vector-search-integrate-with-django-orm.md) - [优化搜索性能](/vector-search-improve-performance.md) - [使用限制](/vector-search-limitations.md) - 事务 diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index 7fd219903831..1a91993e6f65 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -1,11 +1,11 @@ --- title: 向量搜索集成概览 -summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库。 +summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型。 --- # 向量搜索集成概览 -本文档介绍了 TiDB 向量搜索支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 +本文档介绍了 TiDB 向量搜索支持的 AI 框架和嵌入模型。 > **警告:** > @@ -33,39 +33,3 @@ TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌 | 嵌入模型服务提供商 | 教程 | |-----------------------------|---------------------------------------------------------------------------------------------------------------------| | 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 From 57aacb98cbaf8dc82646c675a694cd73d5be9592 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:14:33 +0800 Subject: [PATCH 103/109] Apply suggestions from code review Co-authored-by: Grace Cai --- vector-search-improve-performance.md | 2 +- vector-search-integration-overview.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vector-search-improve-performance.md b/vector-search-improve-performance.md index 9d41ef6f0465..5ff595f561ce 100644 --- a/vector-search-improve-performance.md +++ b/vector-search-improve-performance.md @@ -17,7 +17,7 @@ summary: 了解优化 TiDB 向量搜索性能的最佳实践。 ## 确保向量索引已完全构建 -当插入大量的向量数据时,可能会有部分数据处于 delta 层等待后续的持久化,这一部分的数据会在完成持久化后为其构建向量索引。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#查看索引构建进度)。 +当插入大批量向量数据时,可能会有部分数据处于 Delta 层等待后续的持久化,这一部分的数据会在持久化后才会开始构建向量索引。在向量搜索索引完全构建好后,向量搜索性能才能达到最佳水平。要查看索引构建进度,可参阅[查看索引构建进度](/vector-search-index.md#查看索引构建进度)。 ## 减少向量维数或缩短嵌入时间 diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index 1a91993e6f65..f80fc2aaed3b 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -1,6 +1,6 @@ --- title: 向量搜索集成概览 -summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型。 +summary: 介绍 TiDB 向量搜索支持的 AI 框架和嵌入模型。 --- # 向量搜索集成概览 From 4f3560bfe6412edc41b29c9e263f53fe2f1e8345 Mon Sep 17 00:00:00 2001 From: EricZequan <110292382+EricZequan@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:14:52 +0800 Subject: [PATCH 104/109] Update vector-search-index.md Co-authored-by: Grace Cai --- vector-search-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-index.md b/vector-search-index.md index 6f6cd571b800..26f2227194e9 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -68,7 +68,7 @@ TiDB 目前支持 [HNSW (Hierarchical Navigable Small World)](https://en.wikiped 你只能为固定维度的向量列 (如定义为 `VECTOR(3)` 类型) 创建向量索引,不能为混合维度的向量列 (如定义为 `VECTOR` 类型) 创建向量索引,因为只有维度相同的向量之间才能计算向量距离。 -有关向量搜索索引的约束和限制,请参阅[向量搜索索引 - 使用限制](#使用限制)。 +有关向量搜索索引的约束和限制,请参阅[使用限制](#使用限制)。 ## 使用向量搜索索引 From d82bb7991b4fb865abf3861fdd7ac4dff79bbdf3 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 21 Oct 2024 09:39:17 +0800 Subject: [PATCH 105/109] fix a broken link --- vector-search-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-overview.md b/vector-search-overview.md index ceaee390f46c..8755010f6a2f 100644 --- a/vector-search-overview.md +++ b/vector-search-overview.md @@ -27,7 +27,7 @@ TiDB 向量搜索提供了一种高级的语义搜索功能,可以在文档、 向量嵌入在机器学习中至关重要,是语义相似性搜索的基础。 -TiDB 专门引入了[向量数据类型](/vector-search-data-types.md)以及[向量搜索索引](/vector-search-index),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 +TiDB 专门引入了[向量数据类型](/vector-search-data-types.md)以及[向量搜索索引](/vector-search-index.md),用于优化向量嵌入的存储和检索,增强其在人工智能领域的应用。你可以使用向量类型在 TiDB 中存储向量嵌入,并执行向量搜索查询,找到语义上最相关的数据。 ### 嵌入模型 From c4d049e0746862e35a4c3f107a334429894e2802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 21 Oct 2024 10:40:25 +0800 Subject: [PATCH 106/109] add ORM-non-index doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-integrate-with-django-orm.md | 262 +++++++++++++++++++++ vector-search-integrate-with-peewee.md | 254 ++++++++++++++++++++ vector-search-integrate-with-sqlalchemy.md | 222 +++++++++++++++++ 3 files changed, 738 insertions(+) create mode 100644 vector-search-integrate-with-django-orm.md create mode 100644 vector-search-integrate-with-peewee.md create mode 100644 vector-search-integrate-with-sqlalchemy.md diff --git a/vector-search-integrate-with-django-orm.md b/vector-search-integrate-with-django-orm.md new file mode 100644 index 000000000000..6f6d262a43f9 --- /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-cloud-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-peewee.md b/vector-search-integrate-with-peewee.md new file mode 100644 index 000000000000..064d951dd222 --- /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-cloud-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..6f25678c9c98 --- /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-cloud-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,`` 默认为 `127.0.0.1`。`` 初始密码为空,若你是第一次启动集群,则无需带上此字段。 + +以下为各参数的解释: + +- ``:连接 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 From cc21bc87f3b023d3361234ccb69e1eefeea3e8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Mon, 21 Oct 2024 10:43:18 +0800 Subject: [PATCH 107/109] Revert "remove part of ORM intro" This reverts commit b8a100a82c1af309b9a34f23ac8caa3663f53486. --- TOC.md | 4 +++ vector-search-integration-overview.md | 40 +++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/TOC.md b/TOC.md index 5587c52c958a..1014d0004c2a 100644 --- a/TOC.md +++ b/TOC.md @@ -89,6 +89,10 @@ - [Langchain](/vector-search-integrate-with-langchain.md) - 嵌入模型/服务 - [Jina AI](/vector-search-integrate-with-jinaai-embedding.md) + - ORM 库 + - [SQLAlchemy](/vector-search-integrate-with-sqlalchemy.md) + - [peewee](/vector-search-integrate-with-peewee.md) + - [Django](/vector-search-integrate-with-django-orm.md) - [优化搜索性能](/vector-search-improve-performance.md) - [使用限制](/vector-search-limitations.md) - 事务 diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index f80fc2aaed3b..7fd219903831 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -1,11 +1,11 @@ --- title: 向量搜索集成概览 -summary: 介绍 TiDB 向量搜索支持的 AI 框架和嵌入模型。 +summary: 介绍 TiDB 向量搜索支持的 AI 框架、嵌入模型和 ORM 库。 --- # 向量搜索集成概览 -本文档介绍了 TiDB 向量搜索支持的 AI 框架和嵌入模型。 +本文档介绍了 TiDB 向量搜索支持的 AI 框架、嵌入模型和对象关系映射 (ORM) 库。 > **警告:** > @@ -33,3 +33,39 @@ TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌 | 嵌入模型服务提供商 | 教程 | |-----------------------------|---------------------------------------------------------------------------------------------------------------------| | 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 From b50a16e40be22fe5fdf25240d490d355a4a585af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEricZequan=E2=80=9D?= Date: Tue, 22 Oct 2024 11:36:35 +0800 Subject: [PATCH 108/109] fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “EricZequan” --- vector-search-index.md | 2 +- vector-search-integrate-with-langchain.md | 1 - vector-search-integrate-with-llamaindex.md | 1 - vector-search-integration-overview.md | 8 ++++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/vector-search-index.md b/vector-search-index.md index 26f2227194e9..b1fc54e48a6b 100644 --- a/vector-search-index.md +++ b/vector-search-index.md @@ -130,7 +130,7 @@ SELECT * FROM INFORMATION_SCHEMA.TIFLASH_INDEXES; - 可以通过 `ROWS_STABLE_INDEXED` 和 `ROWS_STABLE_NOT_INDEXED` 列查看索引构建进度。当 `ROWS_STABLE_NOT_INDEXED` 变为 0 时,表示索引构建完成。 - 作为参考,对于一个 500 MiB 的向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 + 作为参考,对于一个 500 MiB 的 768 维向量数据集,构建索引的过程可能需要 20 分钟。索引构建器能够并行地在多个表中构建向量搜索索引。目前不支持调整索引构建器的优先级或速度。 - 可以通过 `ROWS_DELTA_NOT_INDEXED` 列查看 Delta 层中的行数。TiFlash 存储层的数据主要存放在 Delta 层和 Stable 层。Delta 层存储最近插入或更新的行,并根据写入工作量定期将这些行合并到 Stable 层。这个合并过程称为“压缩”。 diff --git a/vector-search-integrate-with-langchain.md b/vector-search-integrate-with-langchain.md index b3ecd4e6480a..b91a7591935d 100644 --- a/vector-search-integrate-with-langchain.md +++ b/vector-search-integrate-with-langchain.md @@ -78,7 +78,6 @@ from langchain_text_splitters import CharacterTextSplitter 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:") diff --git a/vector-search-integrate-with-llamaindex.md b/vector-search-integrate-with-llamaindex.md index eeb9ac5ad701..d3408d396d4e 100644 --- a/vector-search-integrate-with-llamaindex.md +++ b/vector-search-integrate-with-llamaindex.md @@ -77,7 +77,6 @@ from llama_index.vector_stores.tidbvector import TiDBVectorStore 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:") diff --git a/vector-search-integration-overview.md b/vector-search-integration-overview.md index 7fd219903831..08145f67568c 100644 --- a/vector-search-integration-overview.md +++ b/vector-search-integration-overview.md @@ -42,10 +42,10 @@ TiDB 向量搜索支持存储高达 16383 维的向量,可适应大多数嵌 - - - - + + + + From 71257754855dd1b0ba39a3750ac39ebba2349e09 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 22 Oct 2024 16:36:46 +0800 Subject: [PATCH 109/109] Update punctuation --- vector-search-functions-and-operators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector-search-functions-and-operators.md b/vector-search-functions-and-operators.md index 95323ce052cb..9b5995f63338 100644 --- a/vector-search-functions-and-operators.md +++ b/vector-search-functions-and-operators.md @@ -173,7 +173,7 @@ $DISTANCE(p,q)=- INNER\_PROD(p,q)=-\sum \limits _{i=1}^{n}{p_{i}q_{i}}$ 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) (曼哈顿距离),使用的公式为: +计算两个向量之间的 [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}|}$
LanguageORM/ClientHow to installTutorial语言ORM/客户端安装说明教程
Python