Base 目录架构 --- 小白也能看懂的逐层解析
这是
ric-train项目的"地基",所有项目功能都盖在这个地基上。记住一句话:Base 就是项目的工具箱 + 仓库 + 管理员------你要写的所有代码都能直接从这拿现成的。
🧱 先搞懂:为什么需要"Base"这一层?
想象你在装修一套房子:
- 房子本身 = 你的项目(ric-train)
- 水电线路 = 数据库操作(存数据、读数据)
- 门窗 = API 接口(对外提供服务)
- 智能家居 = AI/LLM 集成(调用大模型)
- 工具箱 = 工具函数(各种常用小工具)
Base 就是"把水电线路、智能家居系统、工具箱全部预先装好"------你拿到毛坯房时,基础设施已经配齐了,直接可以开始装修自己的房间。
如果不这样设计,每个新功能都要重新铺水电、装门锁,代码重复且混乱。
📂 全景图
Base/ ← 地基根目录
│
├── Config/ ← 📋 全局配置文件
├── Models/ ← 📦 数据模型(数据的"模板")
│
├── Repository/ ← 🗄️ 数据库操作层(存/取数据)
│
├── Ai/ → 🧠 AI/LLM 集成层(调用大模型)
├── Api/ → 🚪 API 接口层(对外提供服务)
├── Service/ → ⚙️ 业务服务层(核心业务逻辑)
│
├── Client/ → 🔗 第三方服务客户端(对接外部)
│
├── RicUtils/ → 🛠️ 工具箱(各种小工具)
│
├── Meta/ → 🧬 设计模式(代码套路模板)
├── DataSet/ → 📊 数据集管理
│
└── test/ → ✅ 测试代码
第一章:Config/ --- 📋 全局配置管
📝 它是什么
就像一个管理面板,所有"改个值就能影响程序行为"的东西都放在这里。
🏠 生活类比
你家的总电闸 和水阀总开关:
- 全屋总开关:空调开了,全屋供电
- 房间独立开关:每个房间的灯可以独立控制
- Config 就是程序的"总开关"和"自定义面板"
🔧 文件详解
Config/
├── setting.py ← 主配置(从 .env 文件读取一切)
└── logConfig.py ← 日志配置(程序"写日记"的规则)
setting.py --- 配置中心
python
# 原理:读取 .env 文件 → 自动转成 Python 对象 → 类型安全
# 也就是:改一个文件,整个程序的配置都变
from Base.Config.setting import settings
# 📌 可以读取任意配置,用法极度简单
print(settings.mysql.host) # 数据库地址
print(settings.mysql.port) # 数据库端口
print(settings.deepseek.api_key) # DeepSeek API 密钥
print(settings.redis.url) # Redis 地址
为什么不用普通变量? 🤔
| 方式 | 问题 |
|---|---|
普通变量 DB_HOST = "localhost" |
改一个地方要改所有代码 |
配置文件 .env |
改 .env 一个文件就全改了 ✅ |
.env 文件长这样:
env
MYSQL_HOST=localhost
MYSQL_PORT=3306
DEEPSEEK_API_KEY=sk-xxxxx
logConfig.py --- 日志配置
程序运行时会写日记------记录:
- ✅ 正常操作("用户登录成功")
- ⚠️ 警告信息("数据库连接较慢")
- ❌ 错误信息("API 调用失败")
日志配置就是决定日记怎么写、写多详细、写到哪里去。
第二章:Models/ --- 📦 数据模型(数据的"身份证")
📝 它是什么
Models 定义了数据结构长什么样 ------就像身份证模板规定了每张身份证该有姓名、照片、身份证号。
🏠 生活类比
你去银行办业务,柜员让你填的表格:
- 表格规定了:姓名____ 身份证号____ 金额____
- 你填完 → 表格就是一条完整的数据记录
- Models 就是程序里的"表格模板"
🔧 文件详解
Models/
├── BaseEmailModel.py ← 邮件记录表
├── BaseKeywordModel.py ← 关键词表
├── BaseLLMConversationModel.py ← 对话记录表
├── BaseLLMSession.py ← 会话管理表
├── BaseParamsModel.py ← 通用参数表
├── VdbKeyword.py ← 向量库中的关键词
├── VdbLLMConversation.py ← 向量库中的对话
└── studentModel.py ← 学生信息表
核心:Pydantic 模型
python
from pydantic import BaseModel
# 📌 定义"人"的模板
class Person(BaseModel):
name: str # 名字必须是字符串
age: int # 年龄必须是整数
email: str # 邮箱必须是字符串
# 使用
p = Person(name="张三", age=25, email="zhang@email.com")
# ✅ 正确 → 正常创建
p2 = Person(name="李四", age="25岁", email="li@email.com")
# ❌ 错误 → age 写了字符串,不是整数 → Pydantic 自动拒收!
Pydantic 的作用:
| 功能 | 做了什么 |
|---|---|
| 类型检查 | 确保数据格式正确(不能把"25岁"当年龄的整数) |
| 自动转换 | 字符串"25" → 自动转成整数 25 |
| 数据校验 | 限制范围(年龄必须是 0~150) |
| 文档自动生成 | 自动生成接口文档(FastAPI 会用到) |
第三章:Repository/ --- 🗄️ 数据库操作层(核心)
📝 它是什么
Repository 是程序的"仓库管理员"------你不需要知道仓库怎么运作,只需要说"把东西存起来"或"把东西拿来"。
🏠 生活类比
餐厅后厨的食材仓库:
- 厨师(业务代码)要说炒菜 → 不用自己去仓库拿菜
- 仓库管理员(Repository)负责:存取、清点、保鲜
- 厨师只对仓库管理员说"给我拿鸡蛋"即可
🔧 结构总览
Repository/
├── base/ ← 仓库管理员的"培训手册"(抽象基类)
│ ├── baseConnection.py ← 数据库连接的"标准流程"
│ ├── baseDBModel.py ← 数据表的"标准操作"
│ ├── baseVDB.py ← 向量数据库的"标准操作"
│ ├── baseVDBConnection.py ← 向量数据库的"标准连接"
│ └── connectionManager.py ← 多个仓库的"统一调度员"
│
├── connections/ ← 各种数据库的"实际连接方案"
│ ├── mysqlConnection.py ← MySQL 连接
│ ├── postgresConnection.py ← PostgreSQL 连接
│ ├── sqliteConnection.py ← SQLite 连接
│ └── milvusConnection.py ← Milvus(向量数据库)连接
│
├── models/ ← 预定义的数据模型
│ ├── defaultDbModel.py ← 默认模型
│ └── moduleDbModel.py ← 模块级模型
│
├── register.py ← 自动注册(通电即启动)
└── test/ ← 测试用例
📍 3.1 base/ --- 标准操作手册
baseConnection.py --- 数据库连接标准
问题:MySQL 连法、PostgreSQL 连法、SQLite 连法完全不同。
解决 :定义一套统一标准------所有数据库可以这样连接:
python
# 📌 无论后面是什么数据库,调用方式都一样
connection = database.connect() # 连接
cursor = connection.execute(sql) # 执行查询
result = cursor.fetchall() # 获取结果
connection.close() # 关闭连接
baseDBModel.py --- 数据操作的标准(最常用)
这是最核心的文件之一,它定义了"操作数据的标准方法"。
python
# 📌 你只需要定义"表长什么样",然后就能用了
class User(BaseDBModel):
table_alias = "users"
create_table_sql = """
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
age INT
)
"""
id: int | None = None
name: str
age: int
User.set_db_connection(db) # 告诉它连接哪个数据库
# 然后------下面所有操作都是"自动的"!
user = User(name="张三", age=25)
user.save() # ✅ 保存:自动执行 INSERT INTO users ...
found = User.get_by_id(1) # ✅ 查找:自动执行 SELECT * FROM users WHERE id=1
users = User.find_by(age=25) # ✅ 过滤:自动执行 SELECT * FROM users WHERE age=25
users = User.find_all() # ✅ 全部:自动执行 SELECT * FROM users
传统方式 vs 用 BaseDBModel:
python
# ❌ 传统方式:每次都要写 SQL
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("张三", 25))
cursor.execute("SELECT * FROM users WHERE id = %s", (1,))
cursor.execute("SELECT * FROM users WHERE age = %s", (25,))
# ✅ BaseDBModel 方式:不用写 SQL
User(name="张三", age=25).save()
User.get_by_id(1)
User.find_by(age=25)
baseVDB.py --- 向量数据库操作
向量数据库(如 Milvus)专门存"向量"------一串数字。
用途:做语义搜索(找"意思相近"的东西,不是找"字一样"的东西)。
python
# 📌 存向量
vector_embedding = [0.1, 0.2, 0.3, ...] # 从 AI 模型拿到的向量
vdb.store(id="doc_001", vector=vector_embedding, metadata={"source": "法规"})
# 📌 检索向量
query_vector = [0.11, 0.19, 0.32, ...] # 用户问题的向量
results = vdb.search(query_vector, top_k=5) # 找最像的5条
connectionManager.py --- 多数据源调度
如果项目有多个数据库(比如一个 MySQL 存用户、一个 MySQL 存商品、一个 Milvus 存向量),ConnectionManager 负责统一调度:
python
# 📌 一个调度员管所有数据库
manager = ConnectionManager()
# 注册各种数据库
manager.register("main_db", mysql_connection)
manager.register("cache", redis_connection)
manager.register("vector_db", milvus_connection)
# 用时只需要说"给我哪个数据库"
main = manager.get("main_db") # 拿到主数据库
cache = manager.get("cache") # 拿到缓存
vectors = manager.get("vector_db") # 拿到向量数据库
📍 3.2 connections/ --- 各种数据库的"方言翻译"
标准接口定义好了之后,每个数据库需要实现自己的版本。
| 数据库 | 使用场景 | 类比 |
|---|---|---|
| MySQL | 主业务数据(用户、订单、商品) | 即仓库中最常用的货物架 |
| PostgreSQL | 复杂查询、JSON 数据 | 可存特殊物品的架子 |
| SQLite | 本地开发、测试、临时存储 | 办公区的小柜子 |
| Milvus | 向量检索(语义搜索、个性推荐) | 按"感觉"找东西的智能货架 |
它们遵循同样的接口,但各自优化:
python
# 不管你连什么数据库,用起来都一样
mysql = MySQLConnection(host="...", user="root", password="...")
sqlite = SQLiteConnection(database=":memory:") # 内存中的临时数据库
# 同样的操作
mysql.execute("SELECT * FROM users")
sqlite.execute("SELECT * FROM users")
第四章:Ai/ --- 🧠 AI/LLM 集成层
📝 它是什么
AI 集成层是程序和所有大模型(如 ChatGPT、DeepSeek、通义千问)之间的"翻译官"。
🏠 生活类比
你在一家公司上班,想找不同部门办事:
- 没翻译官 :你得学会每个部门的用语("
找财务部说财务语言,找人事部说人事语言" - 有翻译官(AI 集成层):你只对翻译官说"我要报销"→ 翻译官自动用财务部的语言去找人
核心作用 :不管你换哪个大模型,你的代码一个字都不用改。
🔧 结构详解
Ai/
├── base/ ← "翻译官培训手册"
│ ├── baseLlm.py ← LLM 基类(定义"怎么叫大模型")
│ ├── baseMessages.py ← 消息角色(谁说了什么话)
│ ├── baseSetting.py ← 调用配置(温度、长度等参数)
│ └── baseEnum.py ← 枚举(固定选项列表)
│
├── llms/ ← "各语言翻译官"
│ ├── qwenLlm.py ← 通义千问
│ └── deepseekLlm.py ← DeepSeek
│
├── prompt/ ← "话术模板文件夹"
│ └── commonPrompt.py ← 常用提示词模板
│
├── service/ ← "翻译官的工作流程"
│ └── commonService.py ← 通用 AI 业务逻辑
│
└── utils/ ← 翻译官的工具包
└── common.py ← 辅助工具
📍 4.1 base/ --- 培训手册(抽象基类)
baseLlm.py --- "怎么叫大模型"的标准流程
定义了一套通用方法,所有大模型都必须按这个方式调用:
python
# 📌 无论后面是 DeepSeek、Qwen 还是 ChatGPT,写代码的方式都一样
llm.invoke("你好") # 同步调用(等它说完,再继续)
await llm.ainvoke("你好") # 异步调用(不等它,我可以干别的)
llm.stream("你好") # 流式输出(像打字机一样一个字一个字出)
for chunk in llm.stream("写一首诗"):
print(chunk) # 一边输出一边显示
为什么这样设计?
假如你从 DeepSeek 换成了通义千问:
| 场景 | 没翻译官 | 有翻译官 |
|---|---|---|
| 换模型 | 改几十处代码 | 改一行配置 ✅ |
| 出错概率 | 高(手动调接口) | 低(统一封装) |
| 新模型加入 | 所有代码要重写 | 加一个文件即可 |
baseMessages.py --- 消息角色
大模型的聊天中有三种"角色":
python
from Base.Ai.base.baseMessages import (
SystemMessage, # 系统指令(给 AI 设定角色)
UserMessage, # 用户消息(你问的话)
AssistantMessage # 助手回复(AI 的回答)
)
messages = [
SystemMessage("你是银行的信贷风控助手,请专业、简洁地回答问题"),
UserMessage("抵质押率上限是多少?"),
]
# → AI 会按照"你是银行的信贷风控助手"来解答
为什么区分角色?
| 角色 | 作用 | 类比 |
|---|---|---|
| SystemMessage | 设定 AI 的角色和行为规则 | "你是律师,请用法律语言回答" |
| UserMessage | 用户发出的问题或指令 | 用户问"这合法吗?" |
| AssistantMessage | AI 的回复(也可以用来做多轮对话) | 上一轮的回答"根据法规...可能会" |
baseSetting.py --- 调用参数配置
python
# 📌 控制 AI 行为的各种旋钮
class LLMSettings(BaseModel):
temperature: float = 0.7 # 创造力(0=严格,1=天马行空)
max_tokens: int = 4096 # 最长回答字数
top_p: float = 0.9 # 词汇选择范围(越小越保守)
timeout: int = 60 # 超时时间(60秒不说话就断)
temperature 的理解:
temperature=0 → 每次都选概率最高的词 → "银行拒绝了贷款申请"
稳定、可预期、但不灵活
temperature=0.7 → 偶尔选概率次高的词 → "银行未批准贷款申请"
创造力适度、不死板
temperature=1 → 随机选概率前列的词 → "金库驳回钱钱申请"
️ 太随机会胡说八道
📍 4.2 llms/ --- 各模型实现
当前支持两种模型:
python
# 📌 使用完全一致
# DeepSeek
llm = DeepSeekLLM(model="deepseek-chat")
response = llm.invoke("你好")
# 通义千问
llm = QwenLLM(model="qwen-max")
response = llm.invoke("你好")
要加新模型怎么办?
- 在
llms/下新建文件,比如chatgptLlm.py - 继承 BaseLLM,实现
invoke()等方法 - 完成 ✅------所有调你的代码都不用改
📍 4.3 prompt/ --- 提示词模板
提示词 就是给 AI 的"话术模板":
python
# 📌 把提示词"参数化"
from Base.Ai.prompt.commonPrompt import CommonTemplate
# 定义一个模板
email_template = """
你是银行的{role},请用{style}的语气回答用户的问题。
用户的问题:{question}
请基于以下制度文件回答:
{context}
"""
# 传入不同参数,得到不同提示词
prompt = email_template.format(
role="信贷审批专家",
style="严谨",
question="流动资金贷款额度怎么计算?",
context="根据《流动资金贷款管理办法》..."
)
为什么专门管理提示词?
| 方式 | 问题 |
|---|---|
| 散落在代码里的提示词 | 找起来麻烦、改一个要改所有地方 |
| 统一在 prompt/ 下管理 | 一目了然、集中维护、复用 ✅ |
第五章:Service/ --- ⚙️ 业务服务层
📝 它是什么
真正干活的地方------把数据库(Repository)和 AI(Ai)、第三方服务(Client)串起来,完成具体业务。
🏠 生活类比
餐厅厨房的"主厨":
- 仓库管理员(Repository)给你食材
- 翻译官(Ai)帮你叫外卖
- 主厨(Service)决定:要做一盘什么样的菜,先炒什么后炒什么,放多少调料
🔧 服务列表
| 服务 | 做了什么 | 类比 |
|---|---|---|
| aiService.py | 编排 AI 调用:接收问题→检索知识库→生成回答→检查质量 | 主厨炒菜:备菜→下锅→调味→装盘 |
| asrService.py | 语音识别:把录音变成文字 | 听写员 |
| ttsService.py | 语音合成:把文字变成语音 | 播音员 |
| emailService.py | 发送邮件 | 邮递员 |
| keywordService.py | 管理关键词 | 索引卡管理员 |
| llmConversationService.py | 管理对话记录 | 聊天记录保管员 |
| llmSessionService.py | 管理 AI 会话 | 聊天室管理员 |
| MemoryV1Service.py | 记忆服务------让 AI 记住你和它的过往 | AI 的记忆芯片 |
| schedulerService.py | 定时任务调度 | 闹钟+提醒器 |
一个服务的典型流程:
python
# ⭐ 比如 aiService.py 做"智能问答"
def answer_question(user_question: str) -> str:
"""回答用户的问题"""
# 第1步:去数据库检索相关文档(Repository)
docs = knowledge_db.search(user_question) # 找相似文档
# 第2步:调用 AI 生成答案(Ai)
prompt = build_prompt(user_question, docs)
answer = llm.invoke(prompt)
# 第3步:记录对话(Models)
conversation.save(user_question, answer)
# 第4步:返回答案
return answer
Service 层就是要回答"做什么"和"怎么做",它协调所有其他层。
第六章:Client/ --- 🔗 第三方服务客户端
📝 它是什么
项目需要和外部系统打交道------发邮件、存文件、连接云服务------Client 层就是这些"对接工具"。
🏠 生活类比
门口的快递收发点:
- 你想寄快递 → 去收发点 → 收发点找快递公司(第三方)帮你寄
- 你不用知道快递公司怎么运作,只对收发点说"寄这个"就行
🔧 客户端列表
| 客户端 | 做了什么 | 类比 |
|---|---|---|
| emailClient.py | 发送邮件(支持HTML、附件) | 📮 投递邮箱 |
| redisClient.py | 缓存数据(存得快、读得快) | 💨 便签纸(记电话很快) |
| minioClient.py | 存文件(图片、视频、文档) | 📂 云硬盘 |
| asrClient.py | 语音转文字 | 🎤 听写机 |
| ttsClient.py | 文字转语音 | 📢 播音员 |
| jiebaClient.py | 中文分词("我爱北京天安门"→"我/爱/北京天安门") | ✂️ 切词机 |
| mysqlClient.py | MySQL 数据库操作 | 🗄️ 数据库鼠标 |
| milvusClient.py | Milvus 向量数据库 | 🧠 语义搜索引擎 |
| neo4jClient.py | Neo4j 图数据库(关系查询) | 🕸️ 关系地图 |
| schedulerClient.py | 定时任务 | ⏰ 智能闹钟 |
| qwen.py | 通义千问直调(跳过 Ai 封装层) | 🪨 不走翻译官的直线电话 |
| tencent/base.py | 腾讯云服务基类 | 🏢 腾讯公司窗口 |
| tencent/text_audting.py | 腾讯内容审核(过滤违规内容) | 🚨 内容安检门 |
客户端封装的好处:
python
# ❌ 每次发邮件都要写这一大堆
import smtplib
from email.mime.text import MIMEText
msg = MIMEText("内容", "html", "utf-8")
msg["Subject"] = "标题"
msg["From"] = "sender@email.com"
msg["To"] = "receiver@email.com"
server = smtplib.SMTP("smtp.email.com", 587)
server.login("user", "password")
server.sendmail("from", ["to"], msg.as_string())
# ✅ 封装后
emailClient.send(to="receiver@email.com", subject="标题", html="内容")
# 一行搞定!而且自动支持重试、HTML渲染、附件...
第七章:Api/ --- 🚪 API 接口层
📝 它是什么
API 接口层是程序的大门------外部系统、前端页面、手机 App 通过这扇门访问你的程序。
🏠 生活类比
银行柜台的窗口:
- 客户(前端/App)在窗口前排好队
- 窗口(API 接口)只做一件事:收单 → 转给后台办理 → 回复结果
结构
Api/
└── ai/
└── chatApi.py ← AI 问答接口
python
# 📌 FastAPI 风格------定义了"如果有人问问题,该怎么走流程"
from fastapi import APIRouter
from Base.Service.aiService import answer_question
router = APIRouter()
# 定义一个 POST 接口(有人 POST 到 /ai/chat,就执行下面的函数)
@router.post("/ai/chat")
async def chat(request: dict):
question = request.get("question")
# 去 Service 层执行真正的业务逻辑
answer = answer_question(question)
return {"answer": answer, "status": "success"}
用户使用流程:
手机 App 发请求 → API 接口收到 → 转到 Service 层 →
→ Repository 取数据 → AI 生成回答 → 一路返回给手机 App
第八章:RicUtils/ --- 🛠️ 通用工具函数库
📝 它是什么
一个万能工具箱------小到算日期、大到处理 PDF,各种项目里反复用到的功能都在这里。
🧰 工具清单
| 工具 | 功能 | 类比 |
|---|---|---|
| httpUtils.py | 发 HTTP 请求(调别人 API) | 📞 打电话给别的系统 |
| fileUtils.py | 文件读写操作 | 📂 文件柜管理员 |
| dateUtils.py | 日期/时间处理 | 📅 日历小助手 |
| audioFileUtils.py | 音频处理(格式转换、时长) | 🎵 音频剪辑师 |
| pdfUtils.py | PDF 操作(读/写/提取) | 📄 PDF 阅读器 |
| docUtils.py | Word 文档操作 | 📝 Word 助手 |
| excelUtils.py | Excel 操作 | 📊 Excel 助手 |
| dataUtils.py | 数据处理(列表、字典转换) | 🔄 数据转接头 |
| pathUtils.py | 路径处理(找项目根目录) | 🗺️ 路径导航 |
| decoratorUtils.py | 装饰器(通用代码片段模板) | 🏷️ 标签机 |
| redisUtils.py | Redis 操作封装 | 🗝️ 快速取物钥匙 |
| reflectUtils.py | 反射工具(根据字符串找到对应函数) | 🪞 名字→实物映射器 |
用途:
python
# 📌 不用每次自己写这些重复的代码
# 读文件
from Base.RicUtils.fileUtils import read_file
content = read_file("data.csv") # ✅ 一行搞定
# 处理日期
from Base.RicUtils.dateUtils import get_today, add_days
today = get_today() # 今天日期
next_week = add_days(today, 7) # 一周后
# 发请求
from Base.RicUtils.httpUtils import get
data = get("https://api.example.com/data") # ✅ 一行搞定
第九章:Meta/ --- 🧬 设计模式
📝 它是什么
代码世界里有一些"标准化套路",Meta 就是把这些套路写好了,你直接拿来用。
singletonMeta.py --- 单例模式(我是独一份的)
问题:有些东西在整个程序里只能有一个。
- 数据库连接:如果生成两个连接 → 浪费资源、冲突
- 配置管理器:配置改了一个,第二个不知道 → 不一致
解决 :单例模式------保证全宇宙只有一个实例。
python
from Base.Meta.singletonMeta import SingletonMeta
class DatabaseManager(metaclass=SingletonMeta):
"""数据库管理器------整个程序只此一个"""
pass
# 不管 new 多少次,都是同一个对象
a = DatabaseManager()
b = DatabaseManager()
print(a is b) # ✅ True!是同一个东西
第十章:DataSet/ --- 📊 数据集管理
📝 它是什么
管理训练数据/测试数据------加载、切分、预处理。
典型用法
python
from Base.DataSet.DataSet import DataSet
# 加载训练数据
dataset = DataSet.load("training_data.csv")
# 切分成训练集和测试集
train, test = dataset.split(ratio=0.8) # 80%训练,20%测试
# 预处理
train = train.normalize() # 归一化
train = train.remove_duplicates() # 去重
第十一章:程序启动流程
当你把项目跑起来时,Base 会自动做这几件事:
导入 Base 包
│
▼
第一步:加载日志配置
→ 告诉程序"日记怎么记"
│
▼
第二步:加载应用配置
→ 读取 .env 文件,把配置注入程序
│
▼
第三步:初始化日志系统
→ 打开"日记本",准备记录
│
▼
第四步:创建默认 Qwen LLM 实例
→ 让程序准备好和通义千问对话
│
▼
第五步:注册默认数据库连接
→ 数据库就绪,随时可以存/取数据
│
▼
项目开始运行!
你只需要做一件事:
python
import Base # 一行导入,全部初始化自动完成!
第十二章:架构设计模式总结
| 设计模式 | 在哪儿用 | 类比 |
|---|---|---|
| 分层架构 | 整个 Base → Service/Ai/Repository 分层 | 🏢 写字楼:前台→办公层→机房 |
| 抽象工厂 | BaseConnection → MySQL/PostgreSQL/SQLite | 🏭 汽车工厂→能造轿车/SUV/跑车 |
| 单例模式 | SingletonMeta、ConnectionManager | 🆔 全宇宙只有一个我 |
| ORM(对象关系映射) | BaseDBModel 让"Python对象=数据库记录" | 🪞 镜子:代码里改对象=数据库自动更新 |
| 策略模式 | 多个 LLM 实现同一接口 | 🎯 多个翻译官,都懂"中译英" |
| 配置驱动 | .env + Pydantic Settings | 📋 改配置表 → 整个系统行为改变 |
真题演练
Q1:一个用户提问"企业贷款有哪些条件",整个流程是什么?
用户发请求
│
▼
① Api/ai/chatApi.py 收到请求
│
▼
② Service/aiService.py 接手
│
├─ ③ Repository/baseVDB.py 到向量数据库检索相关制度文档
│
├─ ④ Ai/prompt/commonPrompt.py 组装提示词
│ "你是银行的信贷审批专家..."
│
├─ ⑤ Ai/llms/qwenLlm.py 调用大模型
│ 传入:提示词 + 检索到的文档
│ 输出:带引用的详细回答
│
└─ ⑥ Models/BaseLLMConversationModel.py 记录对话
│
▼
返回回答给用户
Q2:如果要支持一个新的数据库(比如 MongoDB),要改哪些文件?
- 在
Repository/connections/下新建mongoConnection.py - 继承
baseConnection.py的标准接口 - 在
register.py注册 - ✅ 完成!
Q3:如果要支持一个新的 AI 模型(比如 ChatGPT),要改哪些文件?
- 在
Ai/llms/下新建chatgptLlm.py - 继承
baseLlm.py,实现invoke()、ainvoke()、stream() - 在配置文件中加上 ChatGPT 的 API Key
- ✅ 完成!
📌 一句话总结
Base 就是项目的"地基 + 水管电路 + 工具箱 + 快递收发点"------
- 你不需要自己铺水管电路(连接数据库、调用 AI 都封装好了)
- 你不需要自己做工具(文件处理、日期处理、发邮件都有现成的)
- 你只需要专注写核心业务逻辑 🎯
python
import Base # 地基就绪了,开始盖楼!