refactor: 引入 SQLAlchemy 多数据库抽象(PostgreSQL + SQL Server)
- 新增 orm.py:按 db_type 构建引擎(postgresql+psycopg2 / mssql+pyodbc), 声明式 Attachment 模型,init_schema 幂等建表 - 重写 db.py 为 SQLAlchemy Core 实现(动态 Table + quote 跨库正确引用、 id/sn 双键回查、跨库分页、先删后插幂等),对外签名不变 - 配置:config.yaml 默认 PostgreSQL,新增 config.mssql.yaml 保留 SQL Server, config_loader 支持可选 driver 与 db_type - write_attachments.py 新增 --init-db - 依赖 requirements.txt 增 sqlalchemy / psycopg2-binary(保留 pyodbc) - README 对齐:修正目标表字段描述并新增数据库抽象层小节
This commit is contained in:
76
README.md
76
README.md
@@ -1,16 +1,23 @@
|
||||
# 布莱迪压力表 - 订单附件识别工具
|
||||
|
||||
根据"总排号"从 SQL Server 查询"新参数"字段,调用大语言模型判断该订单是否携带
|
||||
根据"总排号"从数据库查询"新参数"字段,调用大语言模型判断该订单是否携带
|
||||
附件,并以 JSON 输出结果。支持粗分类(资料/配件/耗材)和精分类("大类:细分
|
||||
类目",具体到针型阀、说明书等)两种粒度。
|
||||
|
||||
> 数据访问层基于 **SQLAlchemy** 抽象,支持 **SQL Server(mssql+pyodbc)** 与
|
||||
> **PostgreSQL(postgresql+psycopg2)** 两种数据库,通过 `config.database.db_type`
|
||||
> 切换。源表/目标表的标识符引用由 SQLAlchemy 按方言自动处理(PG 用 `"名"`,
|
||||
> MSSQL 用 `[名]`),无需改代码。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
`pyodbc` 需要系统已安装对应的 ODBC 驱动。本项目 `config.yaml` 中使用的版本为
|
||||
依赖包含 `sqlalchemy`、`psycopg2-binary`(PostgreSQL 驱动,已自带 libpq)与
|
||||
`pyodbc`(SQL Server 驱动)。使用 **PostgreSQL** 无需额外系统组件;使用
|
||||
**SQL Server** 需要系统已安装对应的 ODBC 驱动,本项目 `config.yaml` 中使用的版本为
|
||||
"ODBC Driver 18 for SQL Server",请按服务器实际安装的驱动版本填写 `database.driver`。
|
||||
若服务器上已有 SQL Server 管理工具/客户端环境,通常已包含该驱动;否则需自行
|
||||
安装 Microsoft 官方 ODBC Driver。
|
||||
@@ -20,9 +27,17 @@ pip install -r requirements.txt
|
||||
编辑 `config.yaml`,填入以下三部分(首次使用需替换为真实值,**请勿将含真实
|
||||
数据库密码 / API Key 的配置文件提交到版本库**):
|
||||
|
||||
- `database`:SQL Server 连接信息(含 `schema`)、表名、字段名。其中
|
||||
`id_column` 为**总排号**列(接口 `--sn` 使用),`id_field` 为数据库**真实 ID**
|
||||
列(接口 `--id` 使用);二者需按源表实际列名填写
|
||||
- `database`:数据库连接信息与源表/字段名。
|
||||
- `db_type`:数据库类型,`postgresql` 或 `mssql`(缺省按 `driver` 是否含
|
||||
"SQL Server" 推断;PostgreSQL 无需 `driver`)。
|
||||
- `server` / `port` / `database` / `username` / `password`:连接信息(两种库通用)。
|
||||
- `schema` / `table` / `id_column` / `id_field` / `param_column`:源表的
|
||||
schema、表名与列名(`id_column` 为**总排号**列,对应 `--sn`;`id_field` 为
|
||||
数据库**真实 ID** 列,对应 `--id`;`param_column` 为**新参数**列)。这些名称
|
||||
按源表实际填写,SQL Server / PostgreSQL 两端保持一致即可。
|
||||
- 仅 `mssql` 需要:`driver`、`trust_server_certificate`。
|
||||
- 切换到 SQL Server 时可直接用 `--config config.mssql.yaml`(已内置原 SQL Server
|
||||
连接信息)。
|
||||
- `llm`:OpenAI 兼容接口的 `base_url`、`api_key`、`model`
|
||||
- `business`:并发数、日志级别、默认分类模式(`default_mode`)、日志目录(`log_dir`)、
|
||||
是否启用"其他"兜底类目(`enable_other_category`,默认关闭)
|
||||
@@ -269,6 +284,10 @@ python write_attachments.py --mode coarse
|
||||
# 先预览将写入/跳过的行,不真正落库
|
||||
python write_attachments.py --dry-run
|
||||
|
||||
# 首次在目标库建表(幂等:仅创建 Common schema 与 Attachment 表,已存在则跳过;
|
||||
# 切换数据库或新环境首次部署前先执行一次)
|
||||
python write_attachments.py --init-db
|
||||
|
||||
# 允许"其他"兜底类目
|
||||
python write_attachments.py --mode fine --enable-other
|
||||
```
|
||||
@@ -285,22 +304,53 @@ python write_attachments.py --mode fine --enable-other
|
||||
`(SN, '无附件', '无')`,下游用 `WHERE MajorCategory <> '无附件'` 取真实附件。
|
||||
- **无法确定/失败**(`has_attachment=null`,含 `not_found` / `llm_*_error` /
|
||||
`db_error`):一律不写,既不当作无附件,也不留脏数据。
|
||||
- **幂等**:写入时对同一总排号先删除旧行再插入本次结果(依赖 `SN, MajorCategory,
|
||||
MinorCategory` 唯一索引),重跑安全。
|
||||
- **幂等**:写入时对同一总排号先删除旧行再插入本次结果(依赖 `(SN, MajorCategory,
|
||||
MinorCategory)` 复合主键保证唯一),重跑安全。
|
||||
|
||||
目标表 `Common.Attachment` 字段:`SN`(nvarchar(30),总排号/关联键)、
|
||||
`MajorCategory`(nvarchar(40),附件大类)、`MinorCategory`(nvarchar(40),附件小类),
|
||||
三者均 `NOT NULL`。
|
||||
目标表 `Common.Attachment` 字段(三列**复合主键**、均 `NOT NULL`;列类型由 ORM 模型
|
||||
`String(30)` / `String(40)` 按方言统一生成:PostgreSQL 端为 `varchar`,SQL Server 端为
|
||||
`nvarchar`):
|
||||
- `SN`:总排号/关联键
|
||||
- `MajorCategory`:附件大类
|
||||
- `MinorCategory`:附件小类
|
||||
|
||||
## 数据库抽象层(多库支持)
|
||||
|
||||
数据访问层已重构为 SQLAlchemy,由两层组成,业务代码(`classifier.py` /
|
||||
`write_attachments.py`)只调用 `db.py` 的 4 个函数,无需感知底层方言:
|
||||
|
||||
- `orm.py`:方言无关的底层。
|
||||
- `build_engine` / `get_engine`:按 `config.database.db_type` 生成 SQLAlchemy Engine
|
||||
(`postgresql+psycopg2` 或 `mssql+pyodbc`),含连接池复用(`pool_pre_ping`)与
|
||||
登录/语句超时;`get_engine` 按连接信息缓存 Engine,避免重复建池。
|
||||
- `Attachment`:目标表 `Common.Attachment` 的声明式 ORM 模型(三列复合主键,
|
||||
`quote=True` 保留大小写),跨库统一的建表/读写入口。
|
||||
- `init_schema`:方言感知地 `CREATE SCHEMA IF NOT EXISTS "Common"` + `create_all`,
|
||||
供 `--init-db` 幂等建表。
|
||||
- `db.py`:基于 SQLAlchemy Core 的查询/落库实现。
|
||||
- 源表(表名/列名含中文、由配置驱动)用动态 `Table(..., quote=True,
|
||||
quote_schema=True)` 构造,标识符引用由 SQLAlchemy 按方言生成(PG 用 `"名"`、
|
||||
MSSQL 用 `[名]`),彻底摆脱手写引号拼接。
|
||||
- 对外 4 个函数签名与旧版完全一致:`fetch_params_by_ids`(支持 `--id` 整型真实 ID
|
||||
与 `--sn` 总排号双键,并回查总排号)、`fetch_param_by_id`、`fetch_all_ids`
|
||||
(`distinct()` + `order_by()` + `limit()/offset(0)`,分页语法跨库自动适配)、
|
||||
`upsert_attachments`(先删后插,依赖复合主键幂等)。
|
||||
|
||||
**切换数据库**:默认 `config.yaml` 指向 PostgreSQL;切回 SQL Server 只需
|
||||
`python write_attachments.py --config config.mssql.yaml`(或 `main.py --config ...`)。
|
||||
两库源表 schema/表名/列名一致,仅需改连接信息与 `db_type`,无需改代码。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
├── config.yaml # 配置文件
|
||||
├── config.yaml # 配置文件(默认 PostgreSQL;含 db_type 切换)
|
||||
├── config.mssql.yaml # SQL Server 版配置(数据库不可达时切换用,--config 指定)
|
||||
├── main.py # 命令行入口:分类并输出 JSON Lines(支持 --summary 在 stderr 打印批汇总;直接 import 同目录各模块)
|
||||
├── write_attachments.py # 写入入口:分类结果落库到 Common.Attachment(全表扫描支持 --limit/--order/--range 按真实 ID 排序与范围过滤;--id/--sn/--ids-file/--mode/--dry-run/--enable-other/--config;运行后打印 token/缓存汇总)
|
||||
├── write_attachments.py # 写入入口:分类结果落库到 Common.Attachment(全表扫描支持 --limit/--order/--range 按真实 ID 排序与范围过滤;--id/--sn/--ids-file/--mode/--dry-run/--enable-other/--init-db/--config;运行后打印 token/缓存汇总)
|
||||
├── requirements.txt
|
||||
├── config_loader.py # YAML 配置读取与校验
|
||||
├── db.py # SQL Server 查询与落库(fetch_params_by_ids 支持按 id/sn 双键查询、fetch_all_ids / upsert_attachments,pyodbc)
|
||||
├── orm.py # 数据库抽象层:SQLAlchemy 引擎构建(mssql/postgresql)、Attachment ORM 模型、init_schema 建表
|
||||
├── db.py # 基于 SQLAlchemy 的查询与落库(fetch_params_by_ids 支持按 id/sn 双键查询、fetch_all_ids / upsert_attachments,跨库无关)
|
||||
├── prompts.py # 提示词与细分类目枚举(唯一需要改分类边界时编辑的文件)
|
||||
├── llm_client.py # LLM 调用 (OpenAI 兼容接口)
|
||||
├── parser.py # LLM 输出格式校验与清洗 → 结构化数据
|
||||
|
||||
Reference in New Issue
Block a user