sdpy-kit 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/PKG-INFO +82 -6
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/README.md +81 -5
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/__init__.py +25 -1
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/__init__.py +23 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/base_db_kit.py +228 -9
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/mysql_kit.py +31 -63
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/pg_kit.py +45 -58
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/sqlite_kit.py +87 -61
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/.gitignore +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/__init__.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/base_service.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/chat_service.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/embedding_service.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/exceptions.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/failover.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/image_service.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/model_builder.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/model_client.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/pool.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/profiles.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/rerank_service.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/runner.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/ai/types.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/anydoc_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/common_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/config/__init__.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/config/kit_config.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/config/log_config.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/crud.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/engine.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/exceptions.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/models/__init__.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/models/base.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/query.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/session.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/db/transaction.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/docx_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/file_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/marker_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/mcp_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/md2doc_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/mineru_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/redis_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/wx_article_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/kit/zvec_kit.py +0 -0
- {sdpy_kit-0.2.2 → sdpy_kit-0.2.4}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sdpy-kit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/MCP/Redis/文件/文档/向量工具集
|
|
5
5
|
Author-email: Clark <changhongyuan@126.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -336,7 +336,7 @@ from kit.db import session_scope, transactional, DBError # 推荐
|
|
|
336
336
|
from kit import session_scope, transactional, DBError # 等价
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
-
### 1. 三个数据库 Kit(
|
|
339
|
+
### 1. 三个数据库 Kit(24 个共享方法 API 完全一致)
|
|
340
340
|
|
|
341
341
|
| 类 | 导入 | 数据库 | extra |
|
|
342
342
|
|----|------|--------|-------|
|
|
@@ -370,13 +370,23 @@ from kit import session_scope, transactional, DBError # 等价
|
|
|
370
370
|
| 表 | `list_tables() -> list[str]` | 列出全部表名 |
|
|
371
371
|
| 表 | `table_exists(table_name) -> bool` | 判断表是否存在 |
|
|
372
372
|
| 表 | `create_tables(models) -> None` | 按模型列表建表 |
|
|
373
|
-
| 表 | `get_table_info(table_name) -> list[dict]` |
|
|
373
|
+
| 表 | `get_table_info(table_name) -> list[dict]` | 获取列信息(按列序;公共键 4 个:`column_name`/`data_type`/`is_nullable`/`column_default`) |
|
|
374
|
+
|
|
375
|
+
> **列表参数(`IN`)**:`query` / `execute` 的 `params` 中值为 `list`/`tuple`/`set`/`frozenset`
|
|
376
|
+
> 时按 `IN` 展开,可直接写 `WHERE id IN :ids`(三库通用)。`IN` **不保证顺序**;参数列表过大
|
|
377
|
+
> 应分批(PG 单语句上限 65535 参数)。
|
|
378
|
+
>
|
|
379
|
+
> **`LIKE` 的方言差异**:SQLite 对 ASCII 不区分大小写,PostgreSQL 区分(用 `ILIKE`);
|
|
380
|
+
> 跨库一致写法:`LOWER(col) LIKE LOWER(:pattern)`。
|
|
381
|
+
>
|
|
382
|
+
> **导出面**:`from kit.db import PgKit, SQLiteKit, build_pg_url, to_vector_literal, …`
|
|
383
|
+
> (`kit` 顶层与 `kit.db` 导出同一套符号)。
|
|
374
384
|
|
|
375
385
|
```python
|
|
376
386
|
from sqlalchemy import BigInteger
|
|
377
387
|
from sqlmodel import SQLModel, Field
|
|
378
388
|
from kit.common_kit import CommonKit
|
|
379
|
-
from kit.db.sqlite_kit import SQLiteKit
|
|
389
|
+
from kit.db import SQLiteKit # 也可 from kit.db.sqlite_kit import SQLiteKit
|
|
380
390
|
|
|
381
391
|
class User(SQLModel, table=True):
|
|
382
392
|
# 主键:64 位整数 + 雪花 ID(应用侧生成,不用数据库自增)
|
|
@@ -393,6 +403,7 @@ users = SQLiteKit.list(User, skip=0, limit=10, order_by="id", desc=True)
|
|
|
393
403
|
|
|
394
404
|
rows = SQLiteKit.query("SELECT * FROM user WHERE name = :name", {"name": "李四"})
|
|
395
405
|
affected = SQLiteKit.execute("UPDATE user SET name = '王五' WHERE id = :id", {"id": user.id})
|
|
406
|
+
rows = SQLiteKit.query("SELECT * FROM user WHERE id IN :ids", {"ids": [1, 2, 3]}) # 列表参数
|
|
396
407
|
|
|
397
408
|
with SQLiteKit.transaction() as session: # 多操作原子提交
|
|
398
409
|
SQLiteKit.create(User, {"name": "批量一"})
|
|
@@ -413,8 +424,9 @@ with SQLiteKit.transaction() as session: # 多操作原子提
|
|
|
413
424
|
|
|
414
425
|
| 方法 | 说明 |
|
|
415
426
|
|------|------|
|
|
416
|
-
| `create_vector_table(table_name, dims, id_col="id", column="embedding", extra_cols=None) -> None` | 建含向量列的表;**`dims` 必填**(SQLite 用 `CHECK` 落实为数据库层约束;PG 硬约束并回读校验已存在表;MySQL
|
|
417
|
-
| `insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> int` |
|
|
427
|
+
| `create_vector_table(table_name, dims, id_col="id", column="embedding", extra_cols=None) -> None` | 建含向量列的表;**`dims` 必填**(SQLite 用 `CHECK` 落实为数据库层约束;PG 硬约束并回读校验已存在表;MySQL 为上限语义)。`extra_cols` 支持 `{列名: 类型串}`(推荐,与 `create_raw_table` 同形)与 `[{"name","type"}]` 两种形态 |
|
|
428
|
+
| `insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> int` | 批量插入向量(**自成一事务并提交**);`ids=None` 时由 Kit 生成雪花 ID;接受 `list[list[float]]` 或二维 numpy 数组 |
|
|
429
|
+
| `build_insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> list[tuple[str, list[dict]]]` | **只拼装、不执行、不管事务**:返回按列集分组的 `(SQL, 参数列表)`,供调用方在**自有事务**内写向量行(见「自有事务内写向量」) |
|
|
418
430
|
| `search_vectors(table_name, query_vector, top_k=10, distance_type="L2", filter_sql=None, exact=True, id_col="id", column="embedding") -> list[dict]` | KNN 检索,按距离升序返回 `{"id", "distance"}`;`exact=True`(默认)禁止近似加速;**MySQL 侧抛 `VectorNotSupportedError`** |
|
|
419
431
|
| `vector_version() -> str` | 向量后端版本;不可用时返回 `"unavailable"`(MySQL 侧为服务端版本号) |
|
|
420
432
|
|
|
@@ -499,6 +511,70 @@ PgKit.search_vectors("my_vec", [0.1] * 384, top_k=5, id_col="vid", column="vec")
|
|
|
499
511
|
> 新增(非破坏性):`VECTOR_CAPABILITIES` 能力声明、`id_col` / `column` 逃生口参数、
|
|
500
512
|
> `insert_vectors` 支持二维 numpy 数组与批量提交。
|
|
501
513
|
|
|
514
|
+
#### 0.2.4 变更
|
|
515
|
+
|
|
516
|
+
| 编号 | 变更 | 影响 |
|
|
517
|
+
|------|------|------|
|
|
518
|
+
| B4 | **入参自洽性校验**(`extra_data` 的键):保留绑定名 `id` / `vec`、与 `id_col` / `column` 重复、不是合法标识符、`id_col == column` → 抛可操作的 `ValueError` | **唯一行为变更**:此前 SQLite 会**静默写坏数据**(如 `id` 列被覆盖)、PG/MySQL 报误导性错误;正常调用**零影响** |
|
|
519
|
+
| — | 新增共享方法 `build_insert_vectors`(只拼装不执行,由 `BaseDbKit` 收敛 → 共享方法 23 → **24**) | 纯新增:可在**自有事务**内写向量行(见下) |
|
|
520
|
+
| — | `create_vector_table` 的 `extra_cols` 支持 `{列名: 类型串}`(与 `create_raw_table` 同形) | 纯新增:既有 `[{"name","type"}]` 形态保留,两者产出 DDL 逐字一致 |
|
|
521
|
+
| — | 后端差异收口:向量列占位符由 `VECTOR_PLACEHOLDER` 驱动(MySQL = `STRING_TO_VECTOR(:vec)`) | 内部整理:公开签名与行为不变 |
|
|
522
|
+
| — | `SQLiteKit.insert_vectors` 的事务获取统一为 `transaction()`(与另两库同构) | 内部一致:行为等价(自成一事务并提交) |
|
|
523
|
+
|
|
524
|
+
#### 0.2.3 变更
|
|
525
|
+
|
|
526
|
+
| 编号 | 变更 | 影响 |
|
|
527
|
+
|------|------|------|
|
|
528
|
+
| B6 | **`PgKit.get_table_info` 按数据库解析语义定位表**(`search_path` 解析到的那张表) | 多 schema 下同名表**不再混行**;单 schema / `public` 场景**无影响**;只接受非限定表名 |
|
|
529
|
+
| — | `query` / `execute` 支持**列表参数**(`IN :ids`,三库通用) | 纯新增;`set`/`frozenset` 自动归一化为 `list` |
|
|
530
|
+
| — | 新增 `SQLiteKit.encode_vector` / `decode_vector`(小端 float32) | 纯新增:可在自有事务内写向量表,见下 |
|
|
531
|
+
| — | 导出面统一:`from kit.db import PgKit, MySqlKit, SQLiteKit, build_pg_url, …` | 纯新增;既有导出未删除/未改名 |
|
|
532
|
+
|
|
533
|
+
**两段查询范式(推荐用法)**:`search_vectors` 只返回 `[{"id", "distance"}]`,载荷二次取回:
|
|
534
|
+
|
|
535
|
+
```python
|
|
536
|
+
hits = SQLiteKit.search_vectors("item_vectors", query_vector, top_k=5)
|
|
537
|
+
rows = SQLiteKit.query("SELECT id, title FROM items WHERE id IN :ids",
|
|
538
|
+
{"ids": [h["id"] for h in hits]}) # IN 不保证顺序,需按 hits 重排
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**自有事务内写向量(推荐:`build_insert_vectors` + `transaction()`)**:
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
from sqlalchemy import text
|
|
545
|
+
|
|
546
|
+
with SQLiteKit.transaction() as session: # 换成 PgKit / MySqlKit 写法相同
|
|
547
|
+
session.execute(text("INSERT INTO docs_item (id, title) VALUES (:id, :t)"),
|
|
548
|
+
{"id": doc_id, "t": title})
|
|
549
|
+
for sql, params in SQLiteKit.build_insert_vectors("docs_doc_vectors", vectors,
|
|
550
|
+
ids=row_ids, extra_data=metas,
|
|
551
|
+
id_col="rowid"):
|
|
552
|
+
session.execute(text(sql), params)
|
|
553
|
+
# 正常退出统一提交;异常自动回滚(多处写入保持同一事务)
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**SQLite 的 DBAPI 变体**(`raw_connection()` 支持 `:name` 命名参数):
|
|
557
|
+
|
|
558
|
+
```python
|
|
559
|
+
conn = SQLiteKit.raw_connection() # 调用方负责 commit / close
|
|
560
|
+
try:
|
|
561
|
+
for sql, params in SQLiteKit.build_insert_vectors("item_vectors", vectors,
|
|
562
|
+
ids=row_ids, extra_data=metas):
|
|
563
|
+
conn.executemany(sql, params)
|
|
564
|
+
conn.commit()
|
|
565
|
+
finally:
|
|
566
|
+
conn.close()
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
> ⚠ 两点约束:① `build_insert_vectors` 输出为 `:name` 风格,**PG / MySQL 的原生 DBAPI 不支持**
|
|
570
|
+
> (psycopg2 / pymysql 需 `%(name)s`),只能经 `transaction()` 的 session 执行;
|
|
571
|
+
> ② SQLite 上**持有未提交写事务**时再调 kit 的**自提交**方法(如 `insert_vectors`)会因另一个连接
|
|
572
|
+
> 拿不到写锁而失败(`OperationalError: database is locked`,约 **6.4s** 后才报错)——
|
|
573
|
+
> 把写入并入**同一个** `transaction()`(如上)即可避免。
|
|
574
|
+
|
|
575
|
+
> 相似度换算建议:SQLite 仅支持 L2,若向量入库前已**归一化**,则 `cos = 1 − L2²/2`;
|
|
576
|
+
> PG 可直接用 `distance_type="COSINE"`。
|
|
577
|
+
|
|
502
578
|
### 3. CRUDBase(配合 session_scope,不自动提交)
|
|
503
579
|
|
|
504
580
|
```python
|
|
@@ -266,7 +266,7 @@ from kit.db import session_scope, transactional, DBError # 推荐
|
|
|
266
266
|
from kit import session_scope, transactional, DBError # 等价
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
### 1. 三个数据库 Kit(
|
|
269
|
+
### 1. 三个数据库 Kit(24 个共享方法 API 完全一致)
|
|
270
270
|
|
|
271
271
|
| 类 | 导入 | 数据库 | extra |
|
|
272
272
|
|----|------|--------|-------|
|
|
@@ -300,13 +300,23 @@ from kit import session_scope, transactional, DBError # 等价
|
|
|
300
300
|
| 表 | `list_tables() -> list[str]` | 列出全部表名 |
|
|
301
301
|
| 表 | `table_exists(table_name) -> bool` | 判断表是否存在 |
|
|
302
302
|
| 表 | `create_tables(models) -> None` | 按模型列表建表 |
|
|
303
|
-
| 表 | `get_table_info(table_name) -> list[dict]` |
|
|
303
|
+
| 表 | `get_table_info(table_name) -> list[dict]` | 获取列信息(按列序;公共键 4 个:`column_name`/`data_type`/`is_nullable`/`column_default`) |
|
|
304
|
+
|
|
305
|
+
> **列表参数(`IN`)**:`query` / `execute` 的 `params` 中值为 `list`/`tuple`/`set`/`frozenset`
|
|
306
|
+
> 时按 `IN` 展开,可直接写 `WHERE id IN :ids`(三库通用)。`IN` **不保证顺序**;参数列表过大
|
|
307
|
+
> 应分批(PG 单语句上限 65535 参数)。
|
|
308
|
+
>
|
|
309
|
+
> **`LIKE` 的方言差异**:SQLite 对 ASCII 不区分大小写,PostgreSQL 区分(用 `ILIKE`);
|
|
310
|
+
> 跨库一致写法:`LOWER(col) LIKE LOWER(:pattern)`。
|
|
311
|
+
>
|
|
312
|
+
> **导出面**:`from kit.db import PgKit, SQLiteKit, build_pg_url, to_vector_literal, …`
|
|
313
|
+
> (`kit` 顶层与 `kit.db` 导出同一套符号)。
|
|
304
314
|
|
|
305
315
|
```python
|
|
306
316
|
from sqlalchemy import BigInteger
|
|
307
317
|
from sqlmodel import SQLModel, Field
|
|
308
318
|
from kit.common_kit import CommonKit
|
|
309
|
-
from kit.db.sqlite_kit import SQLiteKit
|
|
319
|
+
from kit.db import SQLiteKit # 也可 from kit.db.sqlite_kit import SQLiteKit
|
|
310
320
|
|
|
311
321
|
class User(SQLModel, table=True):
|
|
312
322
|
# 主键:64 位整数 + 雪花 ID(应用侧生成,不用数据库自增)
|
|
@@ -323,6 +333,7 @@ users = SQLiteKit.list(User, skip=0, limit=10, order_by="id", desc=True)
|
|
|
323
333
|
|
|
324
334
|
rows = SQLiteKit.query("SELECT * FROM user WHERE name = :name", {"name": "李四"})
|
|
325
335
|
affected = SQLiteKit.execute("UPDATE user SET name = '王五' WHERE id = :id", {"id": user.id})
|
|
336
|
+
rows = SQLiteKit.query("SELECT * FROM user WHERE id IN :ids", {"ids": [1, 2, 3]}) # 列表参数
|
|
326
337
|
|
|
327
338
|
with SQLiteKit.transaction() as session: # 多操作原子提交
|
|
328
339
|
SQLiteKit.create(User, {"name": "批量一"})
|
|
@@ -343,8 +354,9 @@ with SQLiteKit.transaction() as session: # 多操作原子提
|
|
|
343
354
|
|
|
344
355
|
| 方法 | 说明 |
|
|
345
356
|
|------|------|
|
|
346
|
-
| `create_vector_table(table_name, dims, id_col="id", column="embedding", extra_cols=None) -> None` | 建含向量列的表;**`dims` 必填**(SQLite 用 `CHECK` 落实为数据库层约束;PG 硬约束并回读校验已存在表;MySQL
|
|
347
|
-
| `insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> int` |
|
|
357
|
+
| `create_vector_table(table_name, dims, id_col="id", column="embedding", extra_cols=None) -> None` | 建含向量列的表;**`dims` 必填**(SQLite 用 `CHECK` 落实为数据库层约束;PG 硬约束并回读校验已存在表;MySQL 为上限语义)。`extra_cols` 支持 `{列名: 类型串}`(推荐,与 `create_raw_table` 同形)与 `[{"name","type"}]` 两种形态 |
|
|
358
|
+
| `insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> int` | 批量插入向量(**自成一事务并提交**);`ids=None` 时由 Kit 生成雪花 ID;接受 `list[list[float]]` 或二维 numpy 数组 |
|
|
359
|
+
| `build_insert_vectors(table_name, vectors, ids=None, extra_data=None, id_col="id", column="embedding") -> list[tuple[str, list[dict]]]` | **只拼装、不执行、不管事务**:返回按列集分组的 `(SQL, 参数列表)`,供调用方在**自有事务**内写向量行(见「自有事务内写向量」) |
|
|
348
360
|
| `search_vectors(table_name, query_vector, top_k=10, distance_type="L2", filter_sql=None, exact=True, id_col="id", column="embedding") -> list[dict]` | KNN 检索,按距离升序返回 `{"id", "distance"}`;`exact=True`(默认)禁止近似加速;**MySQL 侧抛 `VectorNotSupportedError`** |
|
|
349
361
|
| `vector_version() -> str` | 向量后端版本;不可用时返回 `"unavailable"`(MySQL 侧为服务端版本号) |
|
|
350
362
|
|
|
@@ -429,6 +441,70 @@ PgKit.search_vectors("my_vec", [0.1] * 384, top_k=5, id_col="vid", column="vec")
|
|
|
429
441
|
> 新增(非破坏性):`VECTOR_CAPABILITIES` 能力声明、`id_col` / `column` 逃生口参数、
|
|
430
442
|
> `insert_vectors` 支持二维 numpy 数组与批量提交。
|
|
431
443
|
|
|
444
|
+
#### 0.2.4 变更
|
|
445
|
+
|
|
446
|
+
| 编号 | 变更 | 影响 |
|
|
447
|
+
|------|------|------|
|
|
448
|
+
| B4 | **入参自洽性校验**(`extra_data` 的键):保留绑定名 `id` / `vec`、与 `id_col` / `column` 重复、不是合法标识符、`id_col == column` → 抛可操作的 `ValueError` | **唯一行为变更**:此前 SQLite 会**静默写坏数据**(如 `id` 列被覆盖)、PG/MySQL 报误导性错误;正常调用**零影响** |
|
|
449
|
+
| — | 新增共享方法 `build_insert_vectors`(只拼装不执行,由 `BaseDbKit` 收敛 → 共享方法 23 → **24**) | 纯新增:可在**自有事务**内写向量行(见下) |
|
|
450
|
+
| — | `create_vector_table` 的 `extra_cols` 支持 `{列名: 类型串}`(与 `create_raw_table` 同形) | 纯新增:既有 `[{"name","type"}]` 形态保留,两者产出 DDL 逐字一致 |
|
|
451
|
+
| — | 后端差异收口:向量列占位符由 `VECTOR_PLACEHOLDER` 驱动(MySQL = `STRING_TO_VECTOR(:vec)`) | 内部整理:公开签名与行为不变 |
|
|
452
|
+
| — | `SQLiteKit.insert_vectors` 的事务获取统一为 `transaction()`(与另两库同构) | 内部一致:行为等价(自成一事务并提交) |
|
|
453
|
+
|
|
454
|
+
#### 0.2.3 变更
|
|
455
|
+
|
|
456
|
+
| 编号 | 变更 | 影响 |
|
|
457
|
+
|------|------|------|
|
|
458
|
+
| B6 | **`PgKit.get_table_info` 按数据库解析语义定位表**(`search_path` 解析到的那张表) | 多 schema 下同名表**不再混行**;单 schema / `public` 场景**无影响**;只接受非限定表名 |
|
|
459
|
+
| — | `query` / `execute` 支持**列表参数**(`IN :ids`,三库通用) | 纯新增;`set`/`frozenset` 自动归一化为 `list` |
|
|
460
|
+
| — | 新增 `SQLiteKit.encode_vector` / `decode_vector`(小端 float32) | 纯新增:可在自有事务内写向量表,见下 |
|
|
461
|
+
| — | 导出面统一:`from kit.db import PgKit, MySqlKit, SQLiteKit, build_pg_url, …` | 纯新增;既有导出未删除/未改名 |
|
|
462
|
+
|
|
463
|
+
**两段查询范式(推荐用法)**:`search_vectors` 只返回 `[{"id", "distance"}]`,载荷二次取回:
|
|
464
|
+
|
|
465
|
+
```python
|
|
466
|
+
hits = SQLiteKit.search_vectors("item_vectors", query_vector, top_k=5)
|
|
467
|
+
rows = SQLiteKit.query("SELECT id, title FROM items WHERE id IN :ids",
|
|
468
|
+
{"ids": [h["id"] for h in hits]}) # IN 不保证顺序,需按 hits 重排
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**自有事务内写向量(推荐:`build_insert_vectors` + `transaction()`)**:
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
from sqlalchemy import text
|
|
475
|
+
|
|
476
|
+
with SQLiteKit.transaction() as session: # 换成 PgKit / MySqlKit 写法相同
|
|
477
|
+
session.execute(text("INSERT INTO docs_item (id, title) VALUES (:id, :t)"),
|
|
478
|
+
{"id": doc_id, "t": title})
|
|
479
|
+
for sql, params in SQLiteKit.build_insert_vectors("docs_doc_vectors", vectors,
|
|
480
|
+
ids=row_ids, extra_data=metas,
|
|
481
|
+
id_col="rowid"):
|
|
482
|
+
session.execute(text(sql), params)
|
|
483
|
+
# 正常退出统一提交;异常自动回滚(多处写入保持同一事务)
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**SQLite 的 DBAPI 变体**(`raw_connection()` 支持 `:name` 命名参数):
|
|
487
|
+
|
|
488
|
+
```python
|
|
489
|
+
conn = SQLiteKit.raw_connection() # 调用方负责 commit / close
|
|
490
|
+
try:
|
|
491
|
+
for sql, params in SQLiteKit.build_insert_vectors("item_vectors", vectors,
|
|
492
|
+
ids=row_ids, extra_data=metas):
|
|
493
|
+
conn.executemany(sql, params)
|
|
494
|
+
conn.commit()
|
|
495
|
+
finally:
|
|
496
|
+
conn.close()
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
> ⚠ 两点约束:① `build_insert_vectors` 输出为 `:name` 风格,**PG / MySQL 的原生 DBAPI 不支持**
|
|
500
|
+
> (psycopg2 / pymysql 需 `%(name)s`),只能经 `transaction()` 的 session 执行;
|
|
501
|
+
> ② SQLite 上**持有未提交写事务**时再调 kit 的**自提交**方法(如 `insert_vectors`)会因另一个连接
|
|
502
|
+
> 拿不到写锁而失败(`OperationalError: database is locked`,约 **6.4s** 后才报错)——
|
|
503
|
+
> 把写入并入**同一个** `transaction()`(如上)即可避免。
|
|
504
|
+
|
|
505
|
+
> 相似度换算建议:SQLite 仅支持 L2,若向量入库前已**归一化**,则 `cos = 1 − L2²/2`;
|
|
506
|
+
> PG 可直接用 `distance_type="COSINE"`。
|
|
507
|
+
|
|
432
508
|
### 3. CRUDBase(配合 session_scope,不自动提交)
|
|
433
509
|
|
|
434
510
|
```python
|
|
@@ -23,26 +23,37 @@ Author: Clark Chang
|
|
|
23
23
|
数据库访问通过 kit.db 子包提供(基于 SQLModel)。
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
__version__ = "0.2.
|
|
26
|
+
__version__ = "0.2.4"
|
|
27
27
|
|
|
28
28
|
from kit.db import (
|
|
29
29
|
MYSQL,
|
|
30
30
|
POSTGRESQL,
|
|
31
31
|
SQLITE,
|
|
32
32
|
CRUDBase,
|
|
33
|
+
DEFAULT_DISTANCE_TYPE,
|
|
33
34
|
DBError,
|
|
35
|
+
MySqlKit,
|
|
34
36
|
NotFoundError,
|
|
37
|
+
PgKit,
|
|
38
|
+
SQLiteKit,
|
|
39
|
+
VectorNotSupportedError,
|
|
40
|
+
build_mysql_url,
|
|
41
|
+
build_pg_url,
|
|
42
|
+
build_sqlite_url,
|
|
35
43
|
close_all_engines,
|
|
36
44
|
close_engine,
|
|
37
45
|
create_tables,
|
|
46
|
+
generate_snowflake_ids,
|
|
38
47
|
get_engine,
|
|
39
48
|
get_session,
|
|
40
49
|
list_tables,
|
|
41
50
|
session_scope,
|
|
42
51
|
table_exists,
|
|
52
|
+
to_vector_literal,
|
|
43
53
|
transactional,
|
|
44
54
|
)
|
|
45
55
|
|
|
56
|
+
# 顶层公共面与 kit.db 保持一致(同一套符号,避免两处入口漂移)
|
|
46
57
|
__all__ = [
|
|
47
58
|
# 引擎管理
|
|
48
59
|
"get_engine",
|
|
@@ -51,18 +62,31 @@ __all__ = [
|
|
|
51
62
|
"table_exists",
|
|
52
63
|
"close_all_engines",
|
|
53
64
|
"close_engine",
|
|
65
|
+
# 连接串构造(单一来源)
|
|
66
|
+
"build_pg_url",
|
|
67
|
+
"build_mysql_url",
|
|
68
|
+
"build_sqlite_url",
|
|
54
69
|
# 常量
|
|
55
70
|
"POSTGRESQL",
|
|
56
71
|
"MYSQL",
|
|
57
72
|
"SQLITE",
|
|
73
|
+
# 数据库 Kit
|
|
74
|
+
"PgKit",
|
|
75
|
+
"MySqlKit",
|
|
76
|
+
"SQLiteKit",
|
|
58
77
|
# 会话
|
|
59
78
|
"session_scope",
|
|
60
79
|
"get_session",
|
|
61
80
|
# 异常
|
|
62
81
|
"DBError",
|
|
63
82
|
"NotFoundError",
|
|
83
|
+
"VectorNotSupportedError",
|
|
64
84
|
# CRUD
|
|
65
85
|
"CRUDBase",
|
|
66
86
|
# 事务
|
|
67
87
|
"transactional",
|
|
88
|
+
# 向量工具(公共)
|
|
89
|
+
"to_vector_literal",
|
|
90
|
+
"generate_snowflake_ids",
|
|
91
|
+
"DEFAULT_DISTANCE_TYPE",
|
|
68
92
|
]
|
|
@@ -29,11 +29,19 @@ Author: Clark Chang
|
|
|
29
29
|
- SQLModel 混入类(models/base.py)
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
|
+
from kit.db.base_db_kit import (
|
|
33
|
+
DEFAULT_DISTANCE_TYPE,
|
|
34
|
+
generate_snowflake_ids,
|
|
35
|
+
to_vector_literal,
|
|
36
|
+
)
|
|
32
37
|
from kit.db.crud import CRUDBase
|
|
33
38
|
from kit.db.engine import (
|
|
34
39
|
MYSQL,
|
|
35
40
|
POSTGRESQL,
|
|
36
41
|
SQLITE,
|
|
42
|
+
build_mysql_url,
|
|
43
|
+
build_pg_url,
|
|
44
|
+
build_sqlite_url,
|
|
37
45
|
close_all_engines,
|
|
38
46
|
close_engine,
|
|
39
47
|
create_tables,
|
|
@@ -42,7 +50,10 @@ from kit.db.engine import (
|
|
|
42
50
|
table_exists,
|
|
43
51
|
)
|
|
44
52
|
from kit.db.exceptions import DBError, NotFoundError, VectorNotSupportedError
|
|
53
|
+
from kit.db.mysql_kit import MySqlKit
|
|
54
|
+
from kit.db.pg_kit import PgKit
|
|
45
55
|
from kit.db.session import get_session, session_scope
|
|
56
|
+
from kit.db.sqlite_kit import SQLiteKit
|
|
46
57
|
from kit.db.transaction import transactional
|
|
47
58
|
|
|
48
59
|
__all__ = [
|
|
@@ -53,10 +64,18 @@ __all__ = [
|
|
|
53
64
|
"table_exists",
|
|
54
65
|
"close_all_engines",
|
|
55
66
|
"close_engine",
|
|
67
|
+
# 连接串构造(单一来源,测试/工具可复用)
|
|
68
|
+
"build_pg_url",
|
|
69
|
+
"build_mysql_url",
|
|
70
|
+
"build_sqlite_url",
|
|
56
71
|
# 常量
|
|
57
72
|
"POSTGRESQL",
|
|
58
73
|
"MYSQL",
|
|
59
74
|
"SQLITE",
|
|
75
|
+
# 数据库 Kit
|
|
76
|
+
"PgKit",
|
|
77
|
+
"MySqlKit",
|
|
78
|
+
"SQLiteKit",
|
|
60
79
|
# 会话
|
|
61
80
|
"session_scope",
|
|
62
81
|
"get_session",
|
|
@@ -68,4 +87,8 @@ __all__ = [
|
|
|
68
87
|
"CRUDBase",
|
|
69
88
|
# 事务
|
|
70
89
|
"transactional",
|
|
90
|
+
# 向量工具(公共)
|
|
91
|
+
"to_vector_literal",
|
|
92
|
+
"generate_snowflake_ids",
|
|
93
|
+
"DEFAULT_DISTANCE_TYPE",
|
|
71
94
|
]
|