Files
baiyue-logistics-chat/docs/architecture.md
T

12 KiB
Raw Blame History

模块导航与拆分规范

四阶段拆分已落地:am.py 保留命令及 WSGI 兼容入口,应用工厂和业务代码位于 logistics_chat/,页面样式与脚本位于 static/。本文描述当前结构及后续结构调整约定。

先定位,再阅读

从 AGENTS.md 选择文件,以函数、常量、接口为锚点,搜索后只读取相关实现和调用方。模块移动时更新索引,不保存易失效的行号。默认遵守 Git 忽略规则,排除附件、数据库、日志、备份、虚拟环境和工作草稿。

rg --files
rg -n -F 'calc_freight' logistics_chat/pricing.py
rg -n -F '/api/human/' logistics_chat/routes static/js examples
rg -n '^(def |class |    def )' scripts tests -g '*.py'

PowerShell 下把目录和 -g '*.py' 分开传给 rg。报价字典可能整行很长,搜索时加 --max-columns 200 --max-columns-preview,避免输出整份数据。

当前模块索引

业务范围 实际文件与搜索锚点 联动位置
应用入口与配置 am.py:main、延迟访问的 app;logistics_chat/__init__.py:create_app;config.py:default_config、get_setting;runtime.py:serve_app start.bat、.env.example
Jenkins 灰度部署 Jenkinsfile、Dockerfile;deploy/gray_config.py:GrayConfig;publish-gray.sh、activate-gray.sh、prepare-gray-tls.sh、renew-gray-tls.sh 部署指南;独立持久化数据、证书和回环端口;wsgi.py 提供容器内路径
请求钩子 logistics_chat/hooks.py:rate_limit、no_cache_html 工厂注册钩子;限流状态在 app.extensions['rate_hits']
SQLite 与维护 logistics_chat/db.py:connect、close_connections、init_db、backup_db、save_message、last_user_question、load_context 维护 CLI 在 scripts/;旧会话自动清理仍未启用
历史接口 logistics_chat/history_service.py:new_chat、get_history、get_messages、del_history、clear_all;对应 routes/history.py static/js/chat.js:ensureConv、loadHistory、openConversation
知识检索 logistics_chat/knowledge.py:knowledge_list、search_knowledge knowledge.md 与代码同步,程序不读取该文档
运费与附加费 logistics_chat/pricing.py:RATES、parse_shipping_intent、dims_to_cm、pick_rate、calc_freight、freight_reply、calc_warehouse_card、detect_surcharge、check_island logistics_chat/rates_extra.py 为唯一扩展数据源,根目录同名文件仅兼容转发
运单轨迹 logistics_chat/tracking.py:extract_tracking_no、build_track、CARD_PREFIX、card_to_text static/js/chat.js:fillTrackCard、addTrackCard;模拟节点时间取当前时刻,回归对照需固定时钟
AI 与 SSE logistics_chat/chat_service.py:create_chat_stream、sse;ai_client.py:post_completion、compress_answer、gen_followups routes/chat.py:stream_chat;客户端 doSend、renderError、renderFollowups
人工会话 logistics_chat/human_service.py:human_*;对应 routes/human.py 输入状态在 app.extensions['human_typing'];客户 startHumanPoll;客服 loadQueue、poll、sendReply
附件 logistics_chat/file_service.py:upload_file、cleanup_uploads;routes/files.py:uploaded_file 扩展名/大小/目录由配置提供;客户端 addMsg,客服端 appendMsg
登录、统计、订单、留言、导出 logistics_chat/business_service.py:admin_login、admin_stats、my_orders、add_ticket、list_tickets、export_chat routes/admin.py、routes/business.py;登录页 static/js/admin_login.js
页面 templates/index.html、templates/admin.html、templates/admin_login.html 先加载共享 static/css/theme.css,再加载对应 chat、admin、admin_login 的 CSS/JS;保留全局事件入口
回归 tests/test_rules.py、test_storage.py、test_api.py、test_config.py、test_deployment.py、test_gray_config.py、test_gray_activation.py、test_startup.py、test_maintenance_scripts.py、test_frontend.py;tests/frontend/admin.test.cjs Linux 回退模拟基础设施、实际操作临时文件;模型、数据库及上传隔离;Node 验证异步交互

除标明的根目录文件外,表内缩写的 Python 文件均相对 logistics_chat/。

当前文件布局

am.py                         # CLI;显式请求 am.app 时创建默认 WSGI 应用
rates_extra.py                # 旧导入路径的兼容转发
logistics_chat/
├── __init__.py               # create_app 与显式运行时初始化
├── config.py                 # 根目录 .env、环境变量、稳定根路径、服务/资源配置
├── db.py                     # 连接、schema、历史持久化、备份
├── knowledge.py              # 知识与关键词检索
├── pricing.py                # 运费规则、解析、换算、附加费说明
├── rates_extra.py            # 扩展报价数据
├── tracking.py               # 单号识别、模拟轨迹、卡片协议
├── ai_client.py              # 模型 HTTP、压缩与追问
├── chat_service.py           # 问答编排与 SSE 帧
├── history_service.py        # 历史会话 CRUD
├── human_service.py          # 人工状态与消息
├── business_service.py       # 反馈、统计、登录、订单、留言、CSV
├── file_service.py           # 附件校验、保存、清理
├── hooks.py                  # 限流及 HTML/SSE 缓存头
├── runtime.py                # Waitress / Flask 启动
└── routes/
    ├── __init__.py           # Blueprint 注册
    ├── chat.py
    ├── history.py
    ├── human.py
    ├── admin.py
    ├── business.py
    ├── files.py
    └── pages.py
templates/                    # HTML/Jinja 及原有事件属性
static/css/                   # theme.css 共享令牌;chat/admin/admin_login 页面样式
static/js/                    # chat.js、admin.js、admin_login.js,经典脚本
scripts/                      # 可独立运行的维护 CLI
tests/                        # 按业务模块组织的回归

模块边界与依赖方向

  • 路由只解析请求并包装响应;服务组织业务;规则模块提供确定性计算。依赖方向为 routes → services → rules / db / ai_client,下层不导入路由或根入口。
  • db.py 统一连接、schema 和历史持久化。人工与管理业务的 SQL 放在所属服务,HTTP 路由不执行 SQL。请求及流式请求结束时关闭连接,未提交事务回滚。
  • init_db 包括客服账号、订单与留言表,首次启动只建空表;不内置账号。重复初始化保留已有数据,业务测试从真实初始化结果插入夹具,不另建缺失表。
  • 所有模型 HTTP 经 ai_client.post_completion。保留流式问答 (5, 90)、压缩 (5, 30)、追问 (5, 15) 三组连接/读取超时;不能因共用客户端而合并期限。流结束或取消时释放 HTTP 响应。
  • 模块导入不建库、不备份、不清理附件、不访问模型。create_app 默认显式初始化运行目录、数据库、备份与旧附件清理;INITIALIZE_RUNTIME=False 可禁止这些动作,此时调用方负责提供已有 schema。访问兼容入口 am.app 视为显式创建应用。
  • config.ROOT_DIR 指向仓库根目录,模板/静态目录显式提供给 Flask。数据库、上传、备份、日志使用配置中的绝对路径,避免包文件移动改变数据位置。
  • default_config 用 python-dotenv 读取根目录 .env,不修改 os.environ;只读取已支持的 DEEPSEEK_API_KEY,不展开 ${...}。显式工厂配置优先于进程环境(含空值),再使用文件值。配置在应用创建时确定,修改后重启;真实 .env 不纳入 Git。
  • 限流、输入状态由应用实例持有,不能每请求重置或跨测试应用共享。维护 CLI 和纯规则可用标准库加载,包入口延迟导入 Web 依赖。
  • 单文件围绕一个职责;超过约 300–400 行时检查职责,而非按行数机械拆分。报价数据保持单一来源;兼容转发不复制字典。页面脚本按页面保留既有执行顺序和全局函数,不擅自改为 ES Modules。
  • 配色、字体基线和通用控件放在 theme.css,页面布局放在对应 CSS。客户页通过 body.dark 覆盖主题令牌;新增可翻译文案加入 chat.js 的 I18N,静态文案用 data-i18n。调整样式后检查桌面、390px 窄屏、侧栏、聊天卡片和客服空/活动状态。
  • 客户附件预览由 clearAttachment 管理,轨迹展开由 fillTrackCard 管理。客服 drafts 按 sid 保存草稿,发送成功后只清理已确认发送的内容;常用回复仅填入草稿。renderList 只在展示数据变化时重绘。
  • 客服工作台默认只展示会话列表和全高聊天区;统计使用原生 details 收在「数据概览」。setSessionTab 切换接待/排队列表,setChatView 与 showSessionList 控制 720px 及以下的整屏导航,不结束当前会话。setToolsOpen 控制默认关闭的服务资料:1200px 以上为侧栏,较窄屏为抽屉;列表入口让未选会话的手机用户也能查看留言。

后续结构调整顺序

阶段 范围 验收要求
1. 纯规则 知识、报价、运费、运单识别 边界结果与迁移前一致;固定时钟比较模拟轨迹;导入无运行数据副作用
2. 数据访问 配置、SQLite、备份、附件 临时目录验证 schema 兼容、事务、保留/清理时机和跨目录 CLI
3. 服务/路由 模型、聊天、人工、应用工厂、Blueprint URL/方法/状态/JSON/SSE 不变;保留限流、HTML/SSE 缓存头及根入口
4. 前端 模板与 CSS/JS 仅迁移时对照原资源内容;主动改版时验证语法、资源 URL、加载顺序、响应式和客户/客服页交互

每阶段完成相关验证再推进依赖阶段。鉴权、缺表和计费的业务修复单独说明,避免在结构调整中顺带改行为。

必须保留的接口与数据约定

  • SSE 字段为 t、e、card、replace、suggest、d,保留流式输出、停止、异常及中断保存。
  • chat_service.create_chat_stream 在识别运单号时忽略 [图片]/uploads/... 和 [文件]/uploads/... 路径,避免附件文件名中的时间戳误触发查询;存储与请求仍保留原始附件标记和 URL。
  • 历史卡片以 __CARD__{json} 保存;原 SQLite 表、字段、角色值和历史记录继续可读。
  • 人工申请使用 conv_id,返回 session_id,后续用 sid。状态为 waiting/active/closed,消息方向为 customer/agent。
  • 计费档位、单位换算和舍入保持原样。calc_freight.total 仅含基础运费;附加费尚未统一并入。知识文档与 knowledge_list 同步维护。
  • 上传 URL 保留 /uploads/,默认 10MB,扩展名配置保持不变。原附件保留本地、继续忽略,目录迁移不另建一份数据。
  • 后台鉴权和会话隔离仍不完整,轨迹为模拟数据。Linux 公网验收用 Nginx 全站密码隔离访问,不代表已修复面向客户开放所需的应用权限。

验证与维护

先按 README 安装项目依赖。Windows 使用 .\.venv\Scripts\python.exe -m pytest -v 或同解释器的 -m unittest discover -s tests -v;Linux/macOS 使用 .venv/bin/python。业务测试依赖 Flask,不能用未安装依赖的全局 Python 运行整套测试。模型请求全部模拟,不代表真实 DeepSeek 联调。

路径、函数或资产移动后同步更新根 AGENTS.md、本文、知识资料和 README 目录树。仅改导航时检查路径、符号、命令;改业务时补充相关成功和失败分支,前端改动检查实际页面。