创新实训2024.05.26日志:落地基于硬盘的数据库服务

1. 需求任务列表

以下描述易学大模型软件的web应用的功能。

  1. 用户注册
    1. 用户邮箱,密码,验证码
    2. 开启官方邮箱,用来发验证码(QQ 网易都支持开启smtp协议,找教程,用邮箱不用手机号是为了省买发短信云服务的钱)
    3. 验证码缓存于redis,5min内有效
    4. 验证密码长度,验证码是否正确
    5. 新用户信息保存于mysql,密码使用md5第三方库进行加密
  2. 用户登录
    1. 用户邮箱与密码登录
    2. 校验身份
    3. 根据用户身份信息(也即邮箱,但不要包含密码)生成token
    4. 将token附带在响应中,发回客户端
  3. 用户完善身份信息
    1. 如姓名、年龄、性别
    2. 对自己的简单介绍等
  4. 用户创建专属知识库
    1. 用户可以创建属于自己的知识库,独立于其他用户的知识库存在
    2. 用户可以批量上传任意格式的文件,并将其加入知识库中
  5. 用户创建新会话
    1. 用户可以舍弃之前的上下文,创建一个全新的会话
    2. 该会话用户自己独立的上下文环境
  6. 用户还原历史会话
    1. 用户可以还原之前的历史会话信息,联系上下文继续与大模型chat
  7. 用户进行文件上传会话
    1. 用户可以上传一个或多个文件,但不添加至向量知识库,仅就这几个文件与大模型对话
  8. 用户创建易学知识博客
    1. 仿照csdn等博客网站,可以创建标题,提供博客标签,选择博客封面等进行博客撰写
    2. 支持markdown富文本编辑器
    3. 以markdown格式在网页端显示
  9. 易学贴吧/论坛
    1. 按时间分页显示近期的博客
    2. 用户可以收藏某一篇易学博客
    3. 用户可以在一篇易学博客下进行评论
  10. 管理员后台
    1. 可以查看任意用户的知识库、博客、与大模型的历史会话
    2. 可以封禁某用户及其邮箱,并以邮件的方式通知该用户
    3. 可以解禁某用户及其邮箱,并以邮件的方式通知该用户

2. 硬盘数据库选型

Sqlite(轻量级嵌入式数据库)+SqlAlchemy(Python的orm框架)

Sqlite官网:SQLite Home Page

SqlAlchemy官网:SQLAlchemy - The Database Toolkit for Python

2.1. Sqlite

作为一个嵌入式数据库,Sqlite不以服务进程的方式存在,而是作为文件嵌入在应用进程中。

这里的db文件就是Sqlite的嵌入式数据库文件,每次需要操作数据库时,打开该文件进行curd,操作数据库的会话提交一个事务时(commit),保存修改到该文件。

2.2. SqlAlchemy

SqlAlchemy是Python的一个orm框架,支持多种数据库驱动程序。官方统一地将连接数据库的函数封装了起来(对于所有驱动,都是同一个函数):

from sqlalchemy import create_engine
engine = create_engine("sqlite://", echo=True)

例如sqlite的连接方式就是”sqlite://{你的sqlite的db文件的路径}”。当然,其他数据库也可以,比如通过mysqlconnector进行Mysql数据库的连接。

值得一提的是,SqlAlchemy支持了两种非常强大的机制:类型映射以及依赖管理。此外,他还提供了相当多的语法糖。

类型映射

ORM Mapped Class Configuration — SQLAlchemy 2.0 Documentation

可以将python中的数据类型映射到对应数据库支持的数据类型,采用一个关键词叫做Mapped:

id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
fullname: Mapped[str] = mapped_column(String(30))
nickname: Mapped[Optional[str]]

例如,也许你不知道字符串类型在Sqlite数据库中的具体形式,那么你就可以用Mapped[str]来将python的字符串类型自动映射到Sqlite的字符串类型上,同样的,int,bool,byte等等都可以进行映射。

依赖管理

可以说是关系型数据库外键(Foreign Key)的一个重要机制。

假设现在一个用户(User)有多个与大模型的会话(Conversation),那么显然Conversation表中应该包含对应于用户表主键的外键(例如,User.id)。依赖管理机制可以显式地管理这种一对一、一对多、多对一、多对多的依赖。

在User表的python DDL中:

conversations: Mapped[List["Conversation"]] = relationship(back_populates='owner')  # 拥有的会话集合

List[”Conversation”]意味着一个用户可以有多个会话。

在Conversation的python DDL中:

owner: Mapped["User"] = relationship(back_populates='conversations')

“User”意味着一个会话只能属于一个用户。

CURD语法糖

这种有很多,比如增:

session.add(Conversation(id=conv_id, conv_name=nc.conv_name, create_time=datetime.datetime.utcnow(),user_id=nc.user_id))
session.commit()

这里可以通过对象类型反解析出在哪个表插入数据。

查:

result = session.query(Record).filter(Record.conv_id == conv_id).all()

filter过滤器将充当where的条件,all返回所有满足条件的记录的列表。

其他功能,自查官方文档即可。

3. 数据库表设计

基于目前的需求,设计数据库表共七张:

  1. User:用户信息
  2. Conversation:用户与大模型会话信息
  3. Blog:用户博客信息
  4. KnowledgeBase:用户知识库metaData
  5. Comment:用户博客评论信息
  6. Record:用户与大模型对话记录信息
  7. Administrator:管理员信息

3.1. User表

class User(Base):__tablename__ = 'User'id: Mapped[str] = mapped_column(primary_key=True)email: Mapped[str] = mapped_column()  # 一个邮箱只能注册一个账号password: Mapped[str] = mapped_column()name: Mapped[str] = mapped_column()is_active: Mapped[bool] = mapped_column(default=True)  # 是否被封禁age: Mapped[int] = mapped_column()sex: Mapped[str] = mapped_column()description: Mapped[str] = mapped_column()conversations: Mapped[List["Conversation"]] = relationship(back_populates='owner')  # 拥有的会话集合blogs: Mapped[List["Blog"]] = relationship(back_populates='owner')  # 拥有的博客集合comments: Mapped[List["Comment"]] = relationship(back_populates='owner')  # 拥有的评论集合knowledge_bases: Mapped[List["KnowledgeBase"]] = relationship(back_populates='owner')  # 拥有的知识库集合def __repr__(self):return f'<User(id={self.id}, email={self.email}, name={self.name})>'

3.2. Conversation表

class Conversation(Base):__tablename__ = 'Conversation'id: Mapped[str] = mapped_column(primary_key=True)conv_name: Mapped[str] = mapped_column()create_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow())user_id: Mapped[str] = mapped_column(ForeignKey('User.id'))owner: Mapped["User"] = relationship(back_populates='conversations')records: Mapped[List["Record"]] = relationship(back_populates='conversation')def __repr__(self):return f'<Conversation(id={self.id}, conv_name={self.conv_name})>'

3.3. Blog表

class Blog(Base):__tablename__ = "Blog"id: Mapped[str] = mapped_column(primary_key=True)title: Mapped[str] = mapped_column()content: Mapped[Text] = Column(Text)create_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow())user_id: Mapped[str] = mapped_column(ForeignKey('User.id'))owner: Mapped["User"] = relationship(back_populates='blogs')comments: Mapped[List["Comment"]] = relationship(back_populates='blog')def __repr__(self):return f'<Blog(id={self.id}, title={self.title})>'

3.4. Comment表

class Comment(Base):__tablename__ = "Comment"id: Mapped[str] = mapped_column(primary_key=True)content: Mapped[str] = mapped_column()create_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow())user_id: Mapped[str] = mapped_column(ForeignKey('User.id'))blog_id: Mapped[str] = mapped_column(ForeignKey('Blog.id'))owner: Mapped["User"] = relationship(back_populates='comments')blog: Mapped["Blog"] = relationship(back_populates='comments')def __repr__(self):return f'<Comment(id={self.id}, content={self.content})>'

3.5. KnowledgeBase表

class KnowledgeBase(Base):__tablename__ = "KnowledgeBase"id: Mapped[str] = mapped_column(primary_key=True)name: Mapped[str] = mapped_column()description: Mapped[str] = mapped_column()create_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow())user_id: Mapped[str] = mapped_column(ForeignKey('User.id'))owner: Mapped["User"] = relationship(back_populates='knowledge_bases')def __repr__(self):return f'<KnowledgeBase(id={self.id}, name={self.name})>'

3.6. Administrator表

class Administrator(Base):__tablename__ = "Administrator"id: Mapped[str] = mapped_column(primary_key=True)name: Mapped[str] = mapped_column()password: Mapped[str] = mapped_column()def __repr__(self):return f'<Administrator(id={self.id}, name={self.name})>'

3.7. Record表

class Record(Base):__tablename__ = "Record"id: Mapped[str] = mapped_column(primary_key=True)content: Mapped[str] = mapped_column()is_ai: Mapped[bool] = mapped_column()conv_id: Mapped[str] = mapped_column(ForeignKey('Conversation.id'))conversation: Mapped["Conversation"] = relationship(back_populates='records')def __repr__(self):return f'<Record(id={self.id}, content={self.content})>'

4. ER图

5. 依赖倒置原则下的数据库连接

仿照Spring的容器机制,我们希望一个组件的生命周期是伴随web应用的启动而创建,伴随web应用的结束而销毁。其中数据库连接就是这样的一个组件。

所有这样的组件,均在component包下,数据库连接引擎只是其中一个:

# DB_engine.pydb_lock = Lock()
engine = Nonedef init_db_conn():global engine, db_lockdb_lock.acquire()engine = create_engine(f'sqlite:///{SQLITE_CONNECTION["location"]}')# 注册连接监听 连接时开启外键约束(默认不开启)@event.listens_for(engine, "connect")def enable_foreign_keys(dbapi_connection, connection_record):cursor = dbapi_connection.cursor()cursor.execute("PRAGMA foreign_keys=ON;")logging.info("Sqlite数据库已开启外键约束")cursor.close()db_lock.release()

其中,全局变量engine即为数据库连接引擎。在web应用初始化时,我们调用init_db_conn,随后每次操作数据库,均使用该engine。

这里需要注意的是,Sqlite数据库连接时默认不开启外键约束(例如你可以在User根本不存在的情况下插入一条Conversation),因此我们开启连接时的监听,通过SQL语句打开外键约束选项。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/16250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP+ACCESS客户管理信息系统

摘要 本文介绍了客户管理系统的实现方法。目的在于让大家共享学习和运用这一语言的体会和收获。本系统是Internet/Intranet环境下面向电子商务的客户管理&#xff0c;通过企业管理技术、电子商务和信息技术的高度集成&#xff0c;讨论了客户管理系统的系统构架、系统的工作…

栈和队列的基本见解

1.栈 1.1栈的基本概念和结构&#xff1a; 栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出的原则。 压栈&#xff1a;栈的插入操作叫做进栈/压栈…

python 面对对象 类 魔法方法

魔法方法 一、__init__ 构造函数&#xff0c;可以理解为初始化 触发条件&#xff1a;在实例化的时候就会触发 class People():def __init__(self, name):print(init被执行)self.name namedef eat(self):print(f{self.name}要吃饭)a People(张三) a.eat() # in…

海外抖音TK自动挂机,手机全自动挂机,每天轻松搞2张

海外抖音TK自动挂机&#xff0c;手机全自动挂机&#xff0c;每天轻松搞2张 课程获取方式&#xff1a; https://zzmbk.com/

揭秘Markdown:轻松掌握基础语法,让你的写作更高效、优雅!

文章目录 前言1.标题1.1 使用 和 - 标记一级和二级标题1.2 使用 # 号标记 2.段落格式2.1 字体2.2 分割线2.3 删除线2.4 下划线2.5 脚注 3.列表3.1 无序列表3.2 有序列表3.3 列表嵌套 4.区块4.1 区块中使用列表4.2 列表中使用区块 5.代码代码区块 6.链接7.图片8.表格9.高级技巧…

mysql实战——XtraBackup二进制包安装

1、二进制包下载网站 Software Downloads - Percona 2、安装xtrabackup 解压安装包 tar xvf percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17.tar.gz -C /usr/local 进入目录 cd percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17/ 安装依赖 yum install perl-Dig…

2024.5.25期末测试总结

成绩&#xff1a; 配置&#xff1a; 可能与实际有些出入 题目&#xff1a; 第一题&#xff1a; 代码思路&#xff1a; 一道模拟题&#xff0c;按照公式计算出sumpow(2,i)&#xff0c;判断sum>H&#xff0c;输出 代码&#xff1a; #include<bits/stdc.h> using name…

Java—内部类

Java—内部类 一、内部类二、应用特点三、分类3.1、普通内部类&#xff1a;直接将一个类的定义放在另外一个类的类体中3.2、静态内部类3.3、局部内部类 一、内部类 一个类的定义出现在另外一个类&#xff0c;那么这个出现的类就叫内部类(Inner)。 内部类所在的类叫做外部类(Ou…

在线软件包管理

1.APT工作原理 APT&#xff08;Advanced Packaging Tool&#xff09;是Debian系列Linux操作系统中广泛使用的包管理工具&#xff0c;它为用户提供了从软件仓库搜索、安装、升级和卸载软件包的功能。其工作原理具体分析如下&#xff1a; 1. **集中式软件仓库机制**&#xff1a…

Linux之Nginx

1、Nginx 1.1、什么是Nginx Nginx最初由Igor Sysoev开发&#xff0c;最早在2004年公开发布。它被设计为一个轻量级、高性能的服务器&#xff0c;能够处理大量并发连接而不消耗过多的系统资源。Nginx的架构采用了事件驱动的方式&#xff0c;能够高效地处理请求。它的模块化设计使…

python-情报加密副本

【问题描述】某情报机构采用公用电话传递数据&#xff0c;数据是5位的整数&#xff0c;在传递过程中是加密的。加密规则如下&#xff1a;每位数字都加上8,然后用和除以7的余数代替该数字&#xff0c;再将第1位和第5位交换&#xff0c;第2位和第4位交换。请编写程序&#xff0c;…

Denoising Diffusion Probabilistic Models 全过程概述 + 论文总结

标题&#xff1a;Denoising&#xff08;&#x1f31f;去噪&#xff09;Diffusion Probabilistic Models&#xff08;扩散概率模型&#xff09; 论文&#xff08;NeurIPS会议 CCF A 类&#xff09;&#xff1a;Denoising Diffusion Probabilistic Models 源码&#xff1a;hojona…

卡特兰数-

是组合数学中一种常出现于各种计数问题中的数列。 一、简单介绍 卡特兰数是一个数列&#xff0c;其前几项为&#xff08;从第零项开始&#xff09; : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 47763…

澳大利亚.德国-新闻媒体投放通稿:发表新闻稿需要留意哪些地方-大舍传媒

概述 当我们想要发布新闻稿时&#xff0c;了解目标媒体的特点和要求是至关重要的。本文将介绍澳大利亚和德国的新闻媒体&#xff0c;以及在撰写和投放新闻稿时需要注意的要点&#xff0c;以帮助您更好地与目标受众沟通。 澳大利亚媒体 澳大利亚是一个多元化的国家&#xff0…

Android ListView鼠标模式下ListView回滚问题

概述 在 Android 应用程序中&#xff0c;ListView 是一种常用的控件&#xff0c;用于显示可滚动列表数据。然而&#xff0c;当在鼠标操作模式下使用 ListView 时&#xff0c;可能会遇到一个问题&#xff1a;点击列表项时&#xff0c;列表会回滚到指定位置&#xff0c;这可能会导…

【ML Olympiad】预测地震破坏——根据建筑物位置和施工情况预测地震对建筑物造成的破坏程度

文章目录 Overview 概述Goal 目标Evaluation 评估标准 Dataset Description 数据集说明Dataset Source 数据集来源Dataset Fields 数据集字段 Data Analysis and Visualization 数据分析与可视化Correlation 相关性Hierarchial Clustering 分层聚类Adversarial Validation 对抗…

OFDM通信中的部分内容

纠错编码&#xff1a;在无线通信过程中由于传输过程存在噪声等各种非理想因素&#xff0c;在接收端接收到的信息往往相对于发射信息存在误码&#xff0c;通过纠错编码方式可以对少数非连续的误码进行判断和纠正。举个简单的例子&#xff0c;发射端可能发射的信息为00,01,10,11,…

二叉搜索树的后序遍历序列

二叉搜索树的后序遍历序列 背景题目描述题解 背景 每次重复刷到这题都没有思路,看答案也总需要理解一会,但是下次又忘了,哈哈哈,因此记录一下思路. 题目描述 牛客地址&#xff1a; https://www.nowcoder.com/practice/a861533d45854474ac791d90e447bafd 描述 输入一个整数数…

网络应用层之(1)DHCPv6协议

网络应用层之(1)DHCPv6协议 Author: Once Day Date: 2024年5月26日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-C…

如何从头搭建一个自己的java库并上传到maven官方仓库

创建代码 在代码库根目录执行maven命令&#xff0c;用于快速生成一个基础的Maven项目 mvn archetype:generate \-DgroupIdcom.mycompany \-DartifactIdmy-maven-project \-Dversion1.0.0 \-DarchetypeArtifactIdmaven-archetype-quickstart \-DinteractiveModefalse 这个命令…