网站程序语言那个好,批量下载wordpress文章,学校网站建设运行简介,怎么样再自己的网站做二级域名目录一、任务概述二、数据库升级#xff1a;从 SQLite 到 PostgreSQL2.1 为什么要换 PostgreSQL#xff1f;2.2 在 Ubuntu 上安装 PostgreSQL2.3 安装适配FastAPI的PostgreSQL驱动库2.4 深度改造#xff1a;PostgreSQL 环境搭建与向量存储优化2.4.1 代码重构#xff1a;原生…目录一、任务概述二、数据库升级从 SQLite 到 PostgreSQL2.1 为什么要换 PostgreSQL2.2 在 Ubuntu 上安装 PostgreSQL2.3 安装适配FastAPI的PostgreSQL驱动库2.4 深度改造PostgreSQL 环境搭建与向量存储优化2.4.1 代码重构原生向量存储1. 修改 models.py使用 ARRAY(Float) 类型2. 修改 feature_extractor.py返回 List[float]3. 修改 init_db.py适配新类型4. 修改 main.py移除 pickle 反序列化2.4.2 重置迁移与数据初始化2.4.3 全链路测试一、任务概述在前序的十篇博客中我们一步步从零构建了一个包含完整前后端的“全球证件智能识别系统”。目前我们的后端服务运行在开发环境中使用SQLite这种轻量级的文件数据库本篇博客将完成数据库的迁移完成从SQLite到PostgreSQL的过度。二、数据库升级从 SQLite 到 PostgreSQL2.1 为什么要换 PostgreSQL虽然SQLite对原型开发很友好但PostgreSQL在生产环境具有压倒性优势高并发支持采用多进程架构支持大量客户端同时读写。数据类型丰富原生支持数组Array和 JSONB非常适合存储我们的特征向量无需 pickle 序列化为 bytes可以直接存为浮点数数组和结构化 OCR 结果。生态强大配合pgvector插件可以直接在数据库层面进行向量相似度搜索虽然本项目目前在内存中计算但未来扩展性极佳。2.2 在 Ubuntu 上安装 PostgreSQL首先我们需要在开发机Ubuntu 22.04上安装 PostgreSQL 数据库服务。更新包列表并安装sudoaptupdatesudoaptinstallpostgresql postgresql-contrib启动服务并设置开机自启sudosystemctl start postgresqlsudosystemctlenablepostgresql配置用户和数据库PostgreSQL 安装后默认会创建一个名为postgres的系统用户。我们需要切换到该用户并进入数据库控制台。# 切换到 postgres 用户sudo-i -u postgres# 进入数据库控制台psql在postgres#提示符下执行 SQL 命令来设置密码并创建数据库-- 1. 修改默认用户 postgres 的密码 (请将 mysecretpassword 替换为你的强密码)ALTERUSERpostgres PASSWORDmysecretpassword;-- 2. 创建项目专用数据库CREATEDATABASEcard_db;-- 3. 退出控制台\q退出postgres用户身份exit更新环境变量最后为了让代码连接到这个本地数据库我们需要设置DATABASE_URL环境变量。在当前终端执行或添加到~/.bashrcexportDATABASE_URLpostgresql://postgres:mysecretpasswordlocalhost:5432/card_db2.3 安装适配FastAPI的PostgreSQL驱动库在 FastAPI 项目中连接 PostgreSQL需要安装psycopg2驱动。pipinstallpsycopg2-binary接下来需要修改database.py使其能够根据环境变量动态切换连接地址。这样既保留了本地开发的灵活性连本地库又适应了 Docker 部署连容器库。代码清单database.pyimportosfromsqlmodelimportcreate_engine,Session# 从环境变量中读取数据库连接 URL# 如果环境变量未设置默认使用 PostgreSQL 的本地连接字符串开发环境# 格式: postgresql://user:passwordhost:port/dbnameDATABASE_URLos.getenv(DATABASE_URL,postgresql://postgres:mysecretpasswordlocalhost:5432/card_db)# 创建数据库引擎# 注意PostgreSQL 不需要 check_same_thread 参数那是 SQLite 特有的enginecreate_engine(DATABASE_URL,echoFalse)defget_session(): FastAPI 依赖注入函数用于获取数据库会话 withSession(engine)assession:yieldsession最后修改Alembic 的配置文件alembic.ini该文件通常包含硬编码的数据库 URL。为了让它也能读取环境变量我们需要修改alembic/env.py文件。代码清单alembic/env.py找到run_migrations_online函数修改connectable的获取方式# ... (原有导入)importosfromdatabaseimportDATABASE_URL# -- 导入我们在database.py中定义的URL# ...defrun_migrations_online()-None:Run migrations in online mode.# --- 修改开始使用代码中配置的 URL 覆盖 alembic.ini 中的配置 ---configurationconfig.get_section(config.config_ini_section)configuration[sqlalchemy.url]DATABASE_URL connectableengine_from_config(configuration,prefixsqlalchemy.,poolclasspool.NullPool,)# --- 修改结束 ---withconnectable.connect()asconnection:context.configure(connectionconnection,target_metadatatarget_metadata)withcontext.begin_transaction():context.run_migrations()这样无论在什么环境下运行alembic upgrade head它都会使用database.py中逻辑确定的数据库地址。2.4 深度改造PostgreSQL 环境搭建与向量存储优化在将系统容器化之前我们需要在本地开发环境Ubuntu中基于PostgreSQL对代码进行一次深度重构弃用 Python 的pickle序列化方式改用 PostgreSQL 原生的ARRAY类型来存储图像特征向量。这将显著提升数据的透明度并减少编解码开销。2.4.1 代码重构原生向量存储这是本次改造的核心。我们将修改数据模型、特征提取器和检索逻辑彻底移除pickle直接以浮点数数组Float Array的形式处理特征向量。1. 修改models.py使用ARRAY(Float)类型我们需要引入 SQLAlchemy 的 PostgreSQL 方言来定义数组列。代码清单models.pyfromtypingimportList,OptionalfromsqlmodelimportField,Relationship,SQLModel# 引入 PostgreSQL 特有的数组类型和 Float 类型fromsqlalchemyimportColumn,Floatfromsqlalchemy.dialects.postgresqlimportARRAYclassCountry(SQLModel,tableTrue):id:Optional[int]Field(defaultNone,primary_keyTrue)name:strField(indexTrue)code:strField(uniqueTrue)certificate_templates:List[CertificateTemplate]Relationship(back_populatescountry)classCertificateTemplate(SQLModel,tableTrue):id:Optional[int]Field(defaultNone,primary_keyTrue)name:strField(indexTrue)description:strField()# 图像数据保持为 bytesimage_front_white:bytesField(description正面白光样证图)image_front_uv:bytesField(description正面紫外样证图)image_back_white:bytesField(description反面白光样证图)image_back_uv:bytesField(description反面紫外样证图)# --- 核心修改特征向量改为浮点数数组 ---# sa_columnColumn(ARRAY(Float)) 告诉数据库这是一个浮点数数组列# Python 侧对应的数据类型是 List[float]feature_front_white:List[float]Field(sa_columnColumn(ARRAY(Float)))feature_front_uv:List[float]Field(sa_columnColumn(ARRAY(Float)))feature_back_white:List[float]Field(sa_columnColumn(ARRAY(Float)))feature_back_uv:List[float]Field(sa_columnColumn(ARRAY(Float)))country_id:Optional[int]Field(defaultNone,foreign_keycountry.id)country:Optional[Country]Relationship(back_populatescertificate_templates)2. 修改feature_extractor.py返回 List[float]移除pickle序列化直接返回 Python 列表。代码清单feature_extractor.py(仅展示修改的方法)# ... (保留 Imports, 注意移除 pickle) ...# import pickle -- 删除此行classImageFeatureExtractor:# ... (__init__ 保持不变) ...defextract_features(self,image_bytes:bytes)-list[float]: 接收图像二进制数据返回浮点数特征列表。 # 去色处理等逻辑保持不变imageImage.open(io.BytesIO(image_bytes)).convert(L).convert(RGB)input_tensorself.preprocess(image)input_batchinput_tensor.unsqueeze(0).to(self.device)withtorch.no_grad():output_featuresself.model(input_batch)feature_npoutput_features.cpu().numpy().flatten()# --- 修改直接转换为 Python List 返回 ---returnfeature_np.tolist()3. 修改init_db.py适配新类型由于init_db.py只是负责数据搬运且extractor返回类型已变更为List[float]models.py也接受List[float]因此该文件几乎不需要修改逻辑。注意请确保init_db.py顶部的导入中不再包含 pickle且在extract_features返回空值时例如文件不存在应赋予默认空列表[]而不是b。代码片段修正建议# ...print( - 正在提取特征向量...)# 如果图像存在则提取否则返回空列表 []feature_front_whiteextractor.extract_features(front_white_bytes)iffront_white_byteselse[]# ... (其他字段同理)4. 修改main.py移除 pickle 反序列化在检索逻辑中从数据库取出的数据已经是 List我们只需要将其转回 Numpy Array 即可进行余弦相似度计算。代码清单main.py(修改recognize_document部分)# ... (保留 Imports, 注意移除 pickle) ...# import pickle -- 删除此行# ...app.post(/api/recognize,...)asyncdefrecognize_document(...):# ...# 1. 提取待查询图像的特征 (extractor 现在返回 List[float])# 我们需要将其转换为 numpy array 以进行数学计算query_feature_frontnp.array(extractor.extract_features(front_white_bytes))query_feature_backnp.array(extractor.extract_features(back_white_bytes))# ... (数据库检索逻辑不变) ...fortemplateintemplates:# --- 修改直接从对象属性获取 List并转为 Numpy Array ---# 数据库已经帮我们把 ARRAY(Float) 转回了 Python Listtemplate_feature_frontnp.array(template.feature_front_white)template_feature_backnp.array(template.feature_back_white)# 相似度计算逻辑保持不变 (cosine_similarity 接收 numpy array)sim_frontcosine_similarity(query_feature_front,template_feature_front)sim_backcosine_similarity(query_feature_back,template_feature_back)# ... (后续逻辑不变)# 5. 二次校验紫外荧光图像相似度检查uv_message未发现异常ifbest_match_template.feature_front_uvandbest_match_template.feature_back_uv:# 仅在样证模板包含完整的紫外特征时进行比对print(正在进行紫外荧光特征二次校验...)query_uv_front_bytesbase64.b64decode(request.image_front_uv)query_uv_back_bytesbase64.b64decode(request.image_back_uv)ifquery_uv_front_bytesandquery_uv_back_bytes:# 提取待查询图像的紫外特征# --- 修改直接转为 Numpy Array ---query_feature_uv_frontnp.array(extractor.extract_features(query_uv_front_bytes))query_feature_uv_backnp.array(extractor.extract_features(query_uv_back_bytes))# 反序列化样证的紫外特征# --- 修改直接转为 Numpy Array ---template_feature_uv_frontnp.array(best_match_template.feature_front_uv)template_feature_uv_backnp.array(best_match_template.feature_back_uv)# 计算相似度sim_uv_frontcosine_similarity(query_feature_uv_front,template_feature_uv_front)sim_uv_backcosine_similarity(query_feature_uv_back,template_feature_uv_back)avg_uv_similarity(sim_uv_frontsim_uv_back)/2print(f紫外图像平均相似度:{avg_uv_similarity:.4f})ifavg_uv_similarity0.80:# 境外证真伪相似度阈值uv_message该证存疑请仔细核查else:avg_uv_similarity0.852.4.2 重置迁移与数据初始化由于我们彻底改变了底层数据类型从 Bytes 变为 Array且数据库引擎从 SQLite 换成了 PostgreSQL建议重新生成迁移文件以避免兼容性问题。清理旧的迁移记录删除项目目录下的alembic/versions文件夹内的所有.py文件。删除旧的database.db文件如果存在。生成新的迁移脚本alembic revision --autogenerate -minit_postgres_array然后在生成的py文件头部添加代码importsqlmodel应用迁移到 PostgreSQLalembic upgradehead此时Alembic 会在card_db中创建表且特征列的类型为double precision[]。初始化数据运行脚本将特征向量计算并以数组形式写入 PostgreSQL。python init_db.py2.4.3 全链路测试一切就绪让我们验证这个更先进的数据库架构。启动后端uvicorn main:app --host0.0.0.0 --port8001启动客户端并测试打开 Qt 客户端选择一个国外证件例如“韩国驾照”点击识别。观察点后端日志不应出现 pickle 相关的错误。识别速度理论上与之前持平但省去了序列化步骤CPU 开销略有降低。数据库检查使用psql或 DBeaver 查看数据库参照前面的方法切换到当前的 postgres# 提示符下输入以下命令并回车\c card_db然后使用\dt命令可以查看所有的表。最后输入下面的命令SELECTfeature_front_whiteFROMcertificatetemplateLIMIT1;应该能看到清晰的浮点数数组{0.123, -0.456, ...}而不是乱码般的二进制数据。至此我们成功完成了后端架构向生产级数据库 PostgreSQL 的迁移并实现了特征向量的原生存储。