初始化询价智能体新仓:同步本地工程并排除密钥与 .env。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# 询价智能体:现状清单与新项目提示词
|
||||
|
||||
本目录是新项目的业务合同(普通 Markdown)。实现时以本目录原文为准。`03` 含密钥,不要写入 Git、不要每次都打开。
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `01-现状总览.md` | 语言、框架、数据库、部署、域名、现网端口、目标进程 |
|
||||
| `02-各端职责.md` | 每个端/进程负责什么(含新系统合并) |
|
||||
| `03-配置与密钥清单.md` | 配置项全表 + 生产明文 |
|
||||
| `04-智能体与模型配置.md` | DeepSeek / 千问角色、Graph、字段合同 |
|
||||
| `05-总控提示词.md` | 给新项目的总提示词(含库表开发期直接改) |
|
||||
| `06-Python智能体.md` | 智能体/Worker 端提示词 |
|
||||
| `07-Java主账.md` | 工单/TMS 主账(Jeecg + 低代码,2026-09-12) |
|
||||
| `08-管理后台.md` | Jeecg Vue / Online 后台提示词 |
|
||||
| `09-企微通道.md` | 企微/H5/存档;入站身份 `sender_id` |
|
||||
| `10-TMS对接.md` | TMS V2 协议提示词 |
|
||||
| `11-部署运维.md` | Windows 部署与发布提示词(现网对照 + 并存) |
|
||||
| `12-测试环境部署.md` | 同机测试环境:目录、端口、库、企微、禁碰现网 |
|
||||
| `13-环境对照.md` | 正式 vs 测试:域名、端口、库变量、切流只换 `.env` |
|
||||
| `14-LangGraph与Redis.md` | 何时用 Graph / Redis、怎么用、禁止当真相的边界 |
|
||||
|
||||
相关决策:`docs/2026-09-12-jeecg-lowcode-ledger-decision.md`。
|
||||
|
||||
## 使用方式
|
||||
|
||||
本文件只当总目录。总控看 `05`;做到哪一端再打开那一份(如工单看 `07`,企微看 `09`)。
|
||||
|
||||
1. 先读 `01`~`04`,确认现状。
|
||||
2. 把 `05` 作为新仓库的系统提示词。
|
||||
3. 分端开工见对应 `06`~`11`;测服 `12`;环境 `13`;编排 `14`。
|
||||
4. 字段合同 JSON 拷进新仓库后以那两份文件为准,不要只靠本目录记忆字段。
|
||||
5. 现网服务器操作仍按甲方现网发布流程;不要用测试步骤去切现网目录。
|
||||
|
||||
## 安全
|
||||
|
||||
- `03` 已按 2026-09-11 服务器活动 release 写入生产明文。**不要 push 公开仓库。**
|
||||
- SSH 私钥不写入本目录。
|
||||
@@ -0,0 +1,170 @@
|
||||
# 现状总览:语言、技术、框架、数据库、部署、域名
|
||||
|
||||
## 产品是什么
|
||||
|
||||
货代询价智能体:销售在企业微信私聊/群聊发文字、图片、Excel/PDF;系统抽字段、补问、建工单、查 TMS 报价、需要时建协同群、生成 Excel/PDF 报价、成交闭环。管理后台查看工单、报价、人员、模板、异常。
|
||||
|
||||
当前不是单体,而是多进程组合。
|
||||
|
||||
## 开发语言
|
||||
|
||||
| 语言 | 版本(建议/源码) | 用在哪 |
|
||||
|---|---|---|
|
||||
| Python | 3.12 | 智能体、企微 Worker、LangGraph、LLM/识别/报价/存档 |
|
||||
| Java | 1.8(JDK 8) | JeecgBoot 工单/TMS 主账 |
|
||||
| TypeScript / JavaScript | Node 18 或 20 | Vue3 管理后台;企微 AIBOT 长连接是 Node `.cjs` |
|
||||
| PowerShell | 7(本机开发建议) | 环境导入、累计部署、远程运维 |
|
||||
| SQL | MySQL / PostgreSQL 方言 | Java 业务库、Python 运行账迁移 |
|
||||
|
||||
## 主要框架与库
|
||||
|
||||
### Python(现网)
|
||||
|
||||
- FastAPI 0.137 + Uvicorn:HTTP 入口
|
||||
- LangGraph 1.2.5 + `langgraph-checkpoint-postgres`:业务流程编排与 checkpoint(何时用、怎么用见 `14`)
|
||||
- httpx:出站 HTTP
|
||||
- psycopg / psycopg2:PostgreSQL
|
||||
- redis:队列、限流、token 缓存;现网还有 Worker **全局单例锁**(新系统不要)。何时用见 `14`
|
||||
- openpyxl / PyMuPDF / pypdf:Excel、PDF
|
||||
- cryptography / python-dotenv
|
||||
- PyMySQL:仅 metrics 等旁路读 MySQL(正式写走 Java)
|
||||
|
||||
### Java(现网主账)
|
||||
|
||||
- JeecgBoot 3.5.3
|
||||
- Spring Boot 2.7.10
|
||||
- Spring Cloud / Alibaba 组件在仓库里有,**生产活动形态是单体** `jeecg-system-start`,不是必开微服务
|
||||
- MyBatis-Plus 3.5.1、Druid、Shiro、JWT
|
||||
- MinIO Java SDK、Hutool、Fastjson、Knife4j
|
||||
- 询价业务在 Jeecg 的 inquiry 模块
|
||||
|
||||
### 前端(现网管理后台)
|
||||
|
||||
- JeecgBoot Vue3 3.5.3
|
||||
- Vue 3.2、Vite 3、Ant Design Vue 3、Pinia、TypeScript
|
||||
- pnpm 7.33.x(锁文件 `pnpm-lock v5.4`,不要用 pnpm 11 重新生成锁文件)
|
||||
- Axios、ECharts 等 Jeecg 全家桶
|
||||
|
||||
### 其它运行时
|
||||
|
||||
- Node.js:AIBOT 长连接脚本(只做传输)
|
||||
- Nginx 1.18.0:`C:\nginx-1.18.0`,反代前端与 Java
|
||||
- LibreOffice:报价 Excel → PDF(默认 `C:\Program Files\LibreOffice\program\soffice.exe`)
|
||||
|
||||
## 数据库与存储
|
||||
|
||||
| 组件 | 角色 | 谁写 |
|
||||
|---|---|---|
|
||||
| **MySQL** | 正式业务主账:工单六态、运输段、源报价/客户报价/版本、费用、附件元数据、人员角色、时间线、Jeecg 系统表。库名源码默认 `jeecg-boot` | **仅 Java** |
|
||||
| **PostgreSQL** | 运行账:企微 inbox/outbox、Graph checkpoint、conversation session、suspend、clarification/卡片绑定、LLM/识别/报价任务 | **仅 Python** |
|
||||
| **Redis** | 缓存、LLM 队列、限流。**不能当业务真相** | Python + Java |
|
||||
| **MinIO / S3 兼容** | 报价文件、附件对象;元数据仍在 Java/任务账 | Python `object_storage` + Jeecg 上传配置 |
|
||||
| 本地磁盘 | 企微 spool、release 目录、Nginx 静态、上传目录 | 运维/进程 |
|
||||
|
||||
现网 Redis 另有两样,**新系统都不要**:`wecom:worker:singleton`(全机只准一个 Worker 的锁);按销售 UserID 伪造 TMS 无价/异常。并发靠「一条任务认领 + 超时回收」和「服务只起一份」。
|
||||
|
||||
### 新系统库名(同机 `10.206.0.14`,空库待建,口令新开)
|
||||
|
||||
| | 现网(禁止新系统连接) | 新系统 |
|
||||
|---|---|---|
|
||||
| MySQL 主账 | `jeecg-boot` / 用户 `ytd_jeecg` | 库 `inquiry_robot` / 用户 `inquiry_robot` |
|
||||
| PostgreSQL 运行账 | `ytd_runtime` / 用户 `ytd_runtime` | 库 `inquiry_robot_runtime` / 用户 `inquiry_robot_runtime` |
|
||||
| Redis | db0 前缀 `ytd:prod:node01-07` | **db1**,前缀 `inquiry_robot:` |
|
||||
| MinIO 桶 | `ytd-inquiry` | `inquiry_robot` |
|
||||
|
||||
仍用现网端口 3306 / 5432 / 6379 / 9000。账号口令不要抄现网,由甲方新建。变量名与正式/测试取值见 `13`。
|
||||
|
||||
## 外部系统(非本仓库)
|
||||
|
||||
| 系统 | 职责 |
|
||||
|---|---|
|
||||
| 企业微信 | 私聊、群聊、模板卡、应用消息、AIBOT |
|
||||
| 微盛会话存档 `open.wshoto.com` | 群/会话 Archive、附件下载 |
|
||||
| TMS(友商/自有 TMS V2) | 报价查询、详情、字典、空运锁舱/释放;外部报价与舱位事实 Owner |
|
||||
| DeepSeek API | 意图路由(A)+ 字段语义(B) |
|
||||
| 阿里云百炼/DashScope 千问 | 附件/图片、报价表映射等 |
|
||||
| 现网 Git | 旧仓仅作对照;新项目用自己的远程 |
|
||||
|
||||
## 部署环境
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 形态 | 甲方 Windows 服务器,不可变 release 目录 |
|
||||
| 公网 IP | `129.211.181.80`(SSH 22) |
|
||||
| 主机名 | `10_206_0_15` |
|
||||
| 运行根 | `C:\yutongda` |
|
||||
| 版本目录 | `C:\yutongda\releases\` |
|
||||
| 运维指针 | `C:\yutongda\ops\`(active-release*.json) |
|
||||
| SSH 账号 | `ytd_extdev_0903`,仅 Ed25519 公钥 |
|
||||
| 允许出口 | `38.175.103.103`、`113.119.172.108`、`115.159.76.75` |
|
||||
| 部署方式 | 固定脚本 `Deploy-YtdCumulativeRelease.ps1`,禁止手工覆盖活动目录 |
|
||||
| OS 本机开发 | Windows 10/11 + PowerShell 7 |
|
||||
|
||||
新系统与现网 **同机并存**:不占用上表 `C:\yutongda` 活动指针;TMS、**域名 `ai.ytd-scm.com`、询价企微 `1000010`、AIBOT Bot 与正式相同**。库、Redis 前缀、监听端口另起。运维通知 `1000014` 也相同。并存期不要改 Nginx 回调、不要双连 AIBOT。
|
||||
|
||||
## 公开域名与路径
|
||||
|
||||
| 地址 | 用途 |
|
||||
|---|---|
|
||||
| `https://ai.ytd-scm.com` | 正式站点(Nginx `ai.conf`)。测试环境域名配置与此相同,切流前公网仍进现网 |
|
||||
| `https://ai.ytd-scm.com/inquiry-form` | H5(测试 `.env` 也填这一条) |
|
||||
| `https://ai.ytd-scm.com/inquiry-form/upload` | H5 询价附件上传 |
|
||||
| `/jeecgboot`(生产前端 `VITE_GLOB_API_URL`) | 浏览器到 Java 的反代前缀 |
|
||||
| Java context-path | `/jeecg-boot`(服务端口 8080) |
|
||||
| 现网 Git | 旧仓地址见 `03`;新项目用新远程 |
|
||||
| `https://work.weixin.qq.com/` | 企微卡片跳转占位 |
|
||||
| `https://open.wshoto.com` | 微盛 Archive API 默认基址 |
|
||||
| `https://api.deepseek.com` / `/beta` | DeepSeek |
|
||||
| DashScope 兼容基址(环境变量 `QWEN_BASE_URL`) | 千问 |
|
||||
|
||||
源码里的 `minio.jeecg.com`、`fileview.jeecg.com`、`cas.test.com` 是 Jeecg 模板默认值,**不等于生产**。生产对象存储与域名以服务器环境文件为准。
|
||||
|
||||
## 监听端口
|
||||
|
||||
公网对外只需 **443**(Nginx)。下面多数是本机回环或数据机,不是都要映射到公网。
|
||||
|
||||
### 现网应用口(拆得过细)
|
||||
|
||||
| 端口 | 现网进程 | 新系统 |
|
||||
|---|---|---|
|
||||
| 8080 | Java JeecgBoot | **保留**(主账,本机,Nginx 反代) |
|
||||
| 8810 | Python `agent_api` | **保留**,并承接原 8809/8811 |
|
||||
| 8809 | Python `bridge_api` | **砍**,并进 8810 |
|
||||
| 8811 | Python `wecom_callback` | **砍**,并进 8810 |
|
||||
| 8812 | Python `wecom_robot` | **砍**,现网基本空配置 |
|
||||
| 8813 | AIBOT Bridge | **保留**,仅 127.0.0.1 |
|
||||
| 3100 | Vite 开发服 | **生产不要开** |
|
||||
|
||||
### 基础设施(不是询价业务端口)
|
||||
|
||||
数据在 `10.206.0.14`:MySQL `3306`、PostgreSQL `5432`、Redis `6379`。本机还有 MinIO `9000`。Worker **不占**对外端口。
|
||||
|
||||
新系统并存期应用口:**8180 + 8910 + 8913**,外加 Nginx 80/443。切流前不要占用现网 8080/8810/8813。
|
||||
|
||||
## 目标进程(不要复现现网拆法)
|
||||
|
||||
现网 Python 拆成多个 uvicorn + 五个 Worker,是发布/隔离习惯,**不是业务必需**。新系统交付形态:
|
||||
|
||||
| 进程 | 端口(可沿用) | 职责 |
|
||||
|---|---|---|
|
||||
| Nginx | 443 / 80 | TLS、静态后台、反代 |
|
||||
| 主账 API | 并存时不要用 8080(示例 8180) | 工单、权限、TMS、后台 API |
|
||||
| 智能体 HTTP | 并存时不要用 8810(示例 8910) | H5、企微 HTTP 回调、主账唤醒;**只入队、快回** |
|
||||
| AIBOT 桥 | 并存时不要用 8813(示例 8913)仅回环 | 长连接转发,无业务状态 |
|
||||
| 后台 Worker **一个进程** | 无对外端口 | LLM、识别、报价(LibreOffice)、存档;进程内分并发槽 |
|
||||
|
||||
Worker 并发约定(**不允许系统卡顿,尽量多线程**):
|
||||
|
||||
- **1 个槽专跑 LibreOffice**(避免本机两台 soffice 互抢)。不是整进程单线程。
|
||||
- **2~3 个线程槽跑 HTTP 类**(模型、识别、存档下载、主账)。不同工单并行。
|
||||
- inbox / outbox **独立线程**,禁止和转 PDF 串在一条阻塞线上。
|
||||
- 回调 / H5 **只入队快回**;禁止在请求线程转 PDF、等完整 LLM、忙等 Redis 结果。
|
||||
- 禁止全局大锁把所有询价排成单行。同一任务认领即可。
|
||||
|
||||
不要:群机器人独立 8812(现网空配置);五个 NSSM Worker;把慢活塞回回调请求。
|
||||
|
||||
## 业务六态(Java 唯一)
|
||||
|
||||
询价中、已报价、协商中、已成交、未成交、已关闭。
|
||||
|
||||
补字段、附件识别中、生成文件、异常、人工协同 **不是第七态**,属于 Graph/任务/异常正交状态。
|
||||
@@ -0,0 +1,123 @@
|
||||
# 有多少个端,每个端负责什么
|
||||
|
||||
从「人对着什么说话 / 什么进程在跑」拆,**现网**约 **10 类端**。不要把 Jeecg 自带的演示模块当成询价产品端。
|
||||
|
||||
**新系统不要按现网进程数复制。** 对人仍是企微私聊/群、H5、Vue 后台;对进程合并为:主账 API、智能体 HTTP(含原 8809/8810/8811)、AIBOT 桥、**一个**后台 Worker(原 llm/recognition/quote/archive + 慢活)。8812 不建。详见 `01`「目标进程」。
|
||||
|
||||
## 1. 企业微信销售端(人)
|
||||
|
||||
- 私聊文字询价、图片、文件。
|
||||
- 模板卡片:补问、采用报价、调价、成交/未成交、进群等。
|
||||
- 点开 H5 补问表单或附件上传页。
|
||||
- **不持有**工单主账;只收消息、点卡片。身份以企微推送的 userid 为准,智能体侧解析为 `sender_id`,不要再反向拉取 ID。
|
||||
|
||||
## 2. 企业微信协同群(人 + 产品岗)
|
||||
|
||||
- 销售/产品在群里报文字价、发报价 Excel/PDF/图片。
|
||||
- 空运可复用固定群(环境变量 `WECOM_FIXED_AIR_GROUP_CHAT_IDS`)。
|
||||
- 存档席用户只为会话存档可见,不能当报价应答人。
|
||||
|
||||
## 3. H5 补问 / 附件页(浏览器,挂在智能体 8810)
|
||||
|
||||
- 域名:`https://ai.ytd-scm.com/inquiry-form/{token}`。
|
||||
- 企微卡片打开一次性表单;URL 只有随机 token。
|
||||
- 上传入口:`/inquiry-form/upload`。
|
||||
- 字段快照与流程状态仍在 LangGraph / PostgreSQL。
|
||||
|
||||
## 4. 管理后台 Web(Vue3)
|
||||
|
||||
正式入口为 **新仓库 `inquiry-backend/`**(Jeecg Vue3 + Vite)。与旧仓 Jeecg 前端**运行无关**;旧项目仅对照页面与 API 语义。
|
||||
启动:在 `inquiry-backend/` 执行 `pnpm run dev`。业务只打新主账 `inquiry-api/`(8180)。
|
||||
|
||||
询价相关页面(新仓目录示例):
|
||||
|
||||
| 页面 | 职责 |
|
||||
|---|---|
|
||||
| 工作台 dashboard | 统计展示(读主账投影) |
|
||||
| 工单 ticket | 列表/详情/时间线/状态迁移/异常处理 |
|
||||
| 员工 staff | 企微 userid 与询价业务角色绑定 |
|
||||
| 报价模板 template | Excel 模板上传/启用 |
|
||||
| 识别/生成/存档 | 任务与死信只读 |
|
||||
| 机器人回复 bot-reply | 话术配置 |
|
||||
|
||||
原则:后台 **不创造第二套业务状态**,只读/操作主账。
|
||||
|
||||
## 5. Java 工单/TMS 主账
|
||||
|
||||
入口为 Jeecg 单体启动模块(现网 8080)或新主账进程;**询价业务 API 均为手写模块**(现网包名 `jeecg-module-inquiry`),不是 Online/cgform。新系统替换主账时保持路径语义与后台 `*.api.ts` 可对接,仍禁止 Online 出生产接口。
|
||||
|
||||
负责:
|
||||
|
||||
- 工单与运输段正式主账、六态迁移、owner/权限。
|
||||
- TMS V2:token、签名、字典投影、query/detail/lock/release。
|
||||
- 源报价、客户报价、报价版本、费用、附件元数据。
|
||||
- 群协同绑定、人员角色、时间线、后台 API。
|
||||
- 字典同步接口 `/api/v1/tms/dictionaries/sync`。
|
||||
|
||||
Python 经 `app/jeecg_client.py` 调用。**Java 成功才算正式业务成功**;Graph 字段不能伪造。
|
||||
|
||||
## 6. Python 智能体核(LangGraph + 路由)
|
||||
|
||||
现网智能体运行链(不是 REL25 候选):
|
||||
|
||||
```
|
||||
企微入站 → wecom_worker / callback / archive
|
||||
→ 企微业务处理 + 会话/意图路由
|
||||
→ DeepSeek A 意图 / DeepSeek B·千问语义
|
||||
→ 流程编排(checkpoint、suspend、补问、查价、协同、报价、成交)
|
||||
→ Java / 群 / 报价 Worker / outbox
|
||||
→ 企微唯一外发
|
||||
```
|
||||
|
||||
职责:自然语言只由模型处理;代码只做身份、Schema、类型、权限、状态、版本、唯一性、证据、幂等。
|
||||
|
||||
REL25 候选路由 **未接管**现网企微执行链。新项目不必沿用该目录名。
|
||||
|
||||
## 7. Python HTTP 进程(现网:同一代码树,多个 uvicorn)
|
||||
|
||||
| 进程 | 端口 | 职责 |
|
||||
|---|---|---|
|
||||
| `app.agent_api` | 8810 | 测试询价入口、H5 表单与上传、部分公开页 |
|
||||
| `app.bridge_api` | 8809 | 接收 Java 唤醒;节点 20/21 时钟;识别/报价任务查询过渡;**不直连 MySQL、不自己查 TMS** |
|
||||
| `app.wecom_callback` | 8811 | 企微应用回调、卡片事件 |
|
||||
| `app.wecom_robot` | 8812 | 群机器人回调 |
|
||||
|
||||
**新系统:** 上述四个合成 **一个** FastAPI(或等价),**路由与实现按包分文件**(回调、H5、唤醒各模块),禁止再做一个万行 `app.py`。Nginx 把 `/inquiry-form`、`/wecom/callback`、主账唤醒路径都打到这一端口。8812 不实现,除非产品明确再开群机器人。HTTP 必须线程池快回,慢活进 Worker 槽(见 `06`)。
|
||||
|
||||
## 8. Python Worker 进程(现网五个)
|
||||
|
||||
| Worker | 入口 | 职责 |
|
||||
|---|---|---|
|
||||
| wecom-worker | `app.wecom_worker` | 消费 inbox,业务处理,outbox 外发;现网 Redis 全局单例 |
|
||||
| llm-worker | `app.llm_worker` | DeepSeek/千问队列执行、重试、结果账 |
|
||||
| recognition-worker | `app.recognition_worker` | 附件/图片识别、抽字段、推进 Graph |
|
||||
| quote-worker | `app.quote_generation_worker` | 正式 Excel/PDF、对象存储、Java 附件、企微文件、wake |
|
||||
| archive-worker | `app.archive_worker` | 微盛 Archive 拉消息/文件、部分群指令 |
|
||||
|
||||
现网:同一队列不要起两个同类 Worker。
|
||||
|
||||
**新系统:** 一个 Worker 进程(NSSM/服务只注册一份,靠部署停旧再起新,**不要** Redis `SET NX` 全局单例)。队列条目用「认领 + 超时回收」防同一条消息被两个槽处理。LibreOffice 单槽,HTTP 类 2~3 槽。inbox/outbox 快路径不要和 soffice 串在同一条阻塞线上。Worker **代码**仍按 jobs/llm/graph/channel 分包,不要合成一个 `worker.py`。
|
||||
|
||||
## 9. AIBOT 长连接桥(Node)
|
||||
|
||||
- 现网为 Node 长连接脚本,新项目可仍用 Node 或等价实现
|
||||
- 端口 8813 仅 127.0.0.1(测试环境 8913)
|
||||
- **只传输**,不拥有业务状态
|
||||
|
||||
## 10. 运维/发布端(人 + 脚本)
|
||||
|
||||
- 本机:环境导入脚本、累计部署器(现网)
|
||||
- 服务器:Nginx、NSSM/计划任务类常驻进程、`C:\yutongda\ops` 指针
|
||||
- Git:真实 `.env` 不进包
|
||||
|
||||
## 数据 Owner 一句话
|
||||
|
||||
| 事实 | Owner |
|
||||
|---|---|
|
||||
| 工单六态、报价版本、权限 | Java / MySQL |
|
||||
| 会话、补问点、checkpoint、inbox/outbox | Python / PostgreSQL |
|
||||
| TMS 价格与舱位 | TMS |
|
||||
| 文件字节 | MinIO/S3 |
|
||||
| 用户看到的消息 | 企微(发送成功 ≠ 业务成功) |
|
||||
| 缓存协调、LLM 队列、限流 | Redis(不当真相;见 `14`) |
|
||||
| 询价流程书签 | LangGraph checkpoint(PostgreSQL;见 `14`) |
|
||||
@@ -0,0 +1,72 @@
|
||||
# 智能体与模型配置(功能合同)
|
||||
|
||||
## 模型分工(必须保持)
|
||||
|
||||
| 角色 | 模型默认 | 模式 | 做什么 | 不做什么 |
|
||||
|---|---|---|---|---|
|
||||
| DeepSeek A | `deepseek-v4-flash` + strict `/beta` | `ordered_actions` | 只根据 inbound_facts 判断意图,调用唯一 `route_decision` | 不抽字段、不写状态、不输出给用户的正文 |
|
||||
| DeepSeek B | 同上或普通 base URL | `text_extract` 等 | 文字字段语义、协同字段、报价文字抽取 | 不改 Java 六态 |
|
||||
| 千问文本 | `qwen-plus` | 附件文本/组织 | Excel/PDF 抽出的文本语义 | 不本地正则猜字段 |
|
||||
| 千问视觉 | `qwen3-vl-plus` | 图片 | 只读图上可见内容 | 不推测、不算最终缺项 |
|
||||
| 千问报价表 | 文本模型 | workbook mapping | 把已冻结事实填进清空后的报价模板 | 不发明价格 |
|
||||
|
||||
代码侧:新项目自建模型网关与 tool schema。`LLM_DATA_USAGE_CONFIRMED` 未确认则不得打真实模型。
|
||||
|
||||
## 流程编排(LangGraph)
|
||||
|
||||
**何时用 Graph:** 一单询价会多次挂起(补问、等卡、等主账、等 PDF),需要书签和按版本唤醒。一次性工具调用不要套 Graph。细则见 `14-LangGraph与Redis.md`。
|
||||
|
||||
编排步骤:
|
||||
|
||||
1. 询价字段确认与补问
|
||||
2. 主账正式建单
|
||||
3. TMS 查询与结果分类
|
||||
4. 协同/群路径
|
||||
5. 报价预览、采用、调价
|
||||
6. 报价文件生成等待
|
||||
7. 成交 / 未成交 / 协商中
|
||||
8. 异常、人工、恢复
|
||||
|
||||
**怎么用:** `thread_id` 绑一单;checkpoint 在 PostgreSQL;停靠点中断;入站 `resume` 或 Worker **结构化 wake**(工单号 + quoteVersion + waitVersion)。无 `sender_id` 不进图。正式六态只在主账;图成功不能冒充主账成功。用户文字不能冒充 Worker 完成。
|
||||
|
||||
## 字段合同
|
||||
|
||||
机器可读(拷进新仓库,目录自定,文件名保持):
|
||||
|
||||
- `inquiry-required-fields-v1.json`
|
||||
- `tms-dictionary-projection-v2.json`
|
||||
|
||||
查价必填(激活业务线之后):
|
||||
|
||||
- **海运**:起运港、目的港、品名、货量、整柜或拼柜、箱型箱量
|
||||
箱型箱量是一个原始业务字段;结构化 `containerItems` 只由 DeepSeek B 投影。
|
||||
- **空运**:起运地、目的地、品名、件数、毛重、体积、包装类型
|
||||
- **陆运**按二级类型:国内拼车/整车、跨境集拼/整车、中港(见合同 JSON)
|
||||
|
||||
协同阶段另有协同必填(贸易条款、HS、含电含磁等),点「协同」必须用 **不可变销售原话** 重跑模型 B,不得用卡片口令覆盖。
|
||||
|
||||
取值规则:当前激活必填字段收到非空即采集;本地不得用封闭枚举拒绝用户原文(除合同声明的机器类型)。未激活字段摘要里的 `-` 不是事实。
|
||||
|
||||
## TMS 结果分类(智能体必须能分流)
|
||||
|
||||
| 分类 | 含义 |
|
||||
|---|---|
|
||||
| 有价 | 业务码成功且有报价 |
|
||||
| `TMS_NO_QUOTE_1002` | 无价 |
|
||||
| `TMS_NO_QUOTE_1003` / 合同不匹配 | 业务缺项或投影失败 |
|
||||
| 字典/协议投影失败 | Java 投影失败,不是「没价格」 |
|
||||
| 技术失败 | HTTP/超时/熔断 |
|
||||
|
||||
字典:精确匹配 `source_code`/`source_name`,禁止模糊、正则、别名推断。域:空运机场、包装、陆运地址/车型/运输类型、海运箱型、币种参考。
|
||||
|
||||
## 报价文件
|
||||
|
||||
- 报价 Excel 模板放进新仓库资源目录(10 类模板与现网等价)。
|
||||
- 报价任务由**后台 Worker 的 LibreOffice 槽**写对象存储 + Java 附件 + 企微文件 + Graph wake(现网是独立 quote-worker,新系统不要再拆成单独 Windows 服务)
|
||||
- 群报价识别:群/工单/角色/segment/报价版本/文件 SHA 全过才能改报价状态
|
||||
|
||||
## 运行合同文件
|
||||
|
||||
新系统运行合同声明:**主账、智能体 HTTP、AIBOT 桥、一个后台 Worker**(外加 Nginx/LibreOffice/库),以及制品完整性。不要做成「必须五个 Python 服务」或「必须持有 Redis 单例锁」。
|
||||
|
||||
Redis 只做队列/限流/token 缓存,不当 checkpoint 或六态;用法见 `14`。
|
||||
@@ -0,0 +1,95 @@
|
||||
# 系统提示词:友通达询价智能体 · 新项目(总控)
|
||||
|
||||
你要做一套与现网 **功能与业务合同等价** 的询价智能体。主账产品决策(2026-09-12):采用 **JeecgBoot + 低代码(Online/cgform)**,可保留手写 `jeecg-module-inquiry` 承载六态/TMS 等复杂规则;不要做成单文件上帝模块。详见 `docs/2026-09-12-jeecg-lowcode-ledger-decision.md`。
|
||||
|
||||
先读同目录 `01`~`04`、`13-环境对照.md`、`14-LangGraph与Redis.md`。字段合同用新仓库里的 `inquiry-required-fields-v1.json` 与 `tms-dictionary-projection-v2.json`(从现网拷贝,目录自定)。没读这两份 JSON 不准写字段校验。环境变量名以 `03` 为准;**测试与正式只换变量值**(见 `13`,含 MySQL/PG/Redis/MinIO)。域名、端口、库名不要写死在代码或 YAML 里。
|
||||
|
||||
## 产品闭环(必须全部能走通)
|
||||
|
||||
1. 企微私聊:文字、图片、Excel/PDF 三种询价入口。
|
||||
2. 海运 / 空运 / 陆运(含陆运二级类型)按唯一字段合同补问:完整输入不误补、不漏字段。
|
||||
3. 随时新开询价并保存旧工单;可激活历史工单从精确断点继续;不重放已提交副作用。
|
||||
4. TMS:有价、无价 1002、业务缺项 1003、字典/协议失败、技术异常,分支互不混淆。
|
||||
5. 需要协同时建群或复用空运固定群;群文字与群附件都能形成正确报价版本。
|
||||
6. 采用、调价、Excel/PDF、对象存储、附件登记、企微发送、流程唤醒共用同一 quoteVersion。
|
||||
7. 正式报价后:成交、未成交、协商中;未成交原因、协商调价、终止、超时不串路由。
|
||||
8. 关键异常可恢复;重复事件幂等;过期卡片/晚到消息零错误写入。
|
||||
9. 多段联运、空运锁舱/释放若本迭代不做,必须关闭入口,禁止半可用。
|
||||
10. 单一源码可构建、测试、回滚。
|
||||
|
||||
## 架构硬约束
|
||||
|
||||
- **自然语言语义只允许模型处理**。代码只验证:身份、Schema、类型、权限、状态、版本、目标唯一性、证据、幂等。
|
||||
- **Java(或你选的主账服务)是正式业务 Owner**:六态、报价版本、权限。智能体不得用图状态假装建单成功。
|
||||
- **TMS 是价格与舱位 Owner**。智能体不得直连 TMS;必须经主账适配器(token + 查询 Bearer,锁舱 HMAC)。
|
||||
- **企微是通道**。发送成功 ≠ 业务成功;业务成功也必须走 outbox 幂等。发送人 userid 来自入站报文(`FromUserName` / AIBOT 发送人 → `sender_id`),**禁止**收消息后再调接口获取企微 ID;无 `sender_id` 不入业务。
|
||||
- PostgreSQL(或等价)存运行账(含 Graph checkpoint);MySQL(或等价)存主账;Redis 只做短命协调(队列/限流/token),不当真相;对象存储只存字节。何时用 Graph/Redis 见 `14`。
|
||||
- 每条入站消息只有一个 RouteDecision、一个执行 Owner,禁止新旧双执行。
|
||||
- **代码不允许把系统卡死。** 回调、H5、健康检查、主账 API 必须快回。慢活(LLM、识别、LibreOffice、Archive 下载、长 Graph)进队列,用线程池 / 多槽并行。禁止单线程串行所有工单,禁止在请求线程 `sleep` 空等到模型或 PDF。细则见 `06`。
|
||||
- **代码必须分模块。** 一个包/目录只承担一类职责。禁止把企微解析、Graph、LLM、报价 PDF、TMS 客户端、主账写操作堆进同一个文件或「util/common」上帝模块。进程可以合并(一个 HTTP、一个 Worker),**源码目录不能合并成一坨**。分法见 `06`/`07`/`08`。
|
||||
- **代码必须加详细中文注释。** 无注释或只有「赋值/循环」式空话的提交不算完成。要写清:这个模块/函数做什么、为什么这样、入参出参、副作用(写库、出站、改六态)、幂等、线程与停点、以及容易走错的分支(如 TMS 1002≠1003)。细则见下节。
|
||||
|
||||
## 注释(必须详细)
|
||||
|
||||
语言:**简体中文**(对外 API 名可英文,注释用中文)。
|
||||
|
||||
每个源码文件文件头:本文件职责、属于哪一包、依赖谁、**禁止**在本文件做什么。
|
||||
|
||||
每个公开函数/类/接口/Graph 节点/Handler:
|
||||
|
||||
- 做什么、什么时候被调用
|
||||
- 参数含义与取值约束(如必须已有 `sender_id`、必须带 waitVersion)
|
||||
- 返回值 / 抛错 / 写入哪张表
|
||||
- 会触发的外部副作用(主账、企微、对象存储、LLM 入队)
|
||||
- 并发:是否占用请求线程、哪条槽、同一 thread_id 能否重入
|
||||
- 为什么不采用另一种写法(例:为何不在回调里等 LLM;为何不直连 TMS)
|
||||
|
||||
分支与常量:每个 `if` 业务分叉、错误码、状态迁移旁边写清「何种业务情况」。复杂算法或协议(HMAC、字典 EXACT_ONLY、卡片绑定)按步骤注释。
|
||||
|
||||
允许不写的:语言字面意义已经等于代码的一行(如 `i += 1`)。不允许:整文件零注释、只复制函数名当注释、把密钥写进注释。
|
||||
|
||||
改代码时同步改注释。注释与行为不一致视为缺陷。
|
||||
|
||||
## 技术选型
|
||||
|
||||
可以换框架,但交付形态必须是:
|
||||
|
||||
- 一个主账 API(**JeecgBoot + 低代码**;目录 `inquiry-api/`;并存期示例端口 8180;库 `inquiry_robot`)
|
||||
- **一个**智能体 HTTP(目录 `inquiry-agent/`;H5 + 企微回调 + 主账唤醒;现网 8809/8810/8811 合并)
|
||||
- **一个**后台 Worker(同 `inquiry-agent/`;LLM / 识别 / 报价 / 存档;进程内分槽,见 `01`)
|
||||
- 一个 AIBOT 桥(8813 回环,无业务状态)
|
||||
- 一个管理后台(**Jeecg Vue3**;目录 `inquiry-backend/`;经 `/jeecgboot` 打新主账)
|
||||
- Windows 服务器 + Nginx + 不可变 release
|
||||
- 配置用 `YTD_ENV=prod|test`,对照 `13-环境对照.md`。域名与企微与正式相同:`ai.ytd-scm.com`、应用 `1000010`。测试只换库/端口/Redis/桶。
|
||||
|
||||
不要复现现网五个 Python Worker 和四个 uvicorn。8812 默认不做。不要 Redis Worker 全局单例租约。
|
||||
|
||||
若换栈,必须在设计文档写清迁移映射:端口、环境变量、六态、TMS 路径。
|
||||
|
||||
## 不要做的事
|
||||
|
||||
- 不要把生产密钥、`.env`、私钥写入 Git。
|
||||
- 不要用正则/别名替代 DeepSeek B 的字段语义(合同允许的机器投影除外)。
|
||||
- 不要在智能体内维护第二套工单状态机。
|
||||
- 不要为了「先跑起来」对真实 TMS **LOCK/RELEASE** 或真实客户群发消息。查价允许用 `03` 现网 TMS。
|
||||
- 不要做按企微 userid 在 Redis 里伪造 TMS 无价/异常。1002/技术失败用单测 stub 覆盖即可。
|
||||
- 不要做 Redis Worker 全局单例租约(`wecom:worker:singleton` / `SET NX` 挡双开)。一份进程靠 Windows 服务 + 发布先停旧再起新;同一条消息靠任务认领防重入。
|
||||
- 询价企微与正式相同(`1000010` 及回调 URL),不要新建应用、不要改现网后台回调。运维 `1000014` 相同;测试进程告警正文带 `[test]`。并存期不要双连 AIBOT。
|
||||
- 不要在收到聊天后再调企微接口获取用户 ID;只用入站 `sender_id`。
|
||||
- 不要写会卡顿整机的实现:回调里同步调模型/转 PDF、全局一把锁串行全部询价、主循环里忙等 Redis 结果。I/O 用线程池或多线程槽;LibreOffice **例外**只许 1 槽。
|
||||
- 不要把不同功能堆在一起:禁止单文件过万行、禁止 `graph.py`/`wecom_business.py` 类上帝文件、禁止一个 handler 处理全部卡片。新功能进对应模块,不要往入口文件追加。
|
||||
- 不要用无关 Jeecg 演示模块冒充询价主账;Online/cgform **允许**用于询价相关生产页与 API(2026-09-12 决策)。不要另起第二套与 Jeecg 并行的后台登录壳(除非明确迁移期)。
|
||||
|
||||
## 库表变更(开发期间)
|
||||
|
||||
实现中只要缺表、缺字段、字段类型/长度不够、索引不够:**直接改**,不要停下来等确认。
|
||||
|
||||
- 写成 **版本化迁移**(主账 MySQL、运行账 PostgreSQL 分目录),可重复执行、有回滚说明。
|
||||
- 只动新系统库 `inquiry_robot` / `inquiry_robot_runtime`。**禁止** ALTER/建表现网 `jeecg-boot`、`ytd_runtime`。
|
||||
- 业务合同字段变了:同步改新仓库里的那两份 JSON 与 API,不要只改库。
|
||||
- 删列、改名、改语义:迁移里写清数据怎么搬;测试库可以做。
|
||||
- 改完在会话里用一两句话说明迁了什么,不必先问「能不能加字段」。
|
||||
|
||||
## 工作方式
|
||||
|
||||
按端拆分实现,顺序建议:主账 API 与数据模型 → 智能体编排与字段合同 → 企微通道 → TMS 适配 → 后台只读 → 部署。每端使用 `06`~`11` 对应提示词;Graph/Redis 实现前先读 `14`。验收以真实企微 fresh 事件为准,健康检查 HTTP 200 不算业务完成。
|
||||
@@ -0,0 +1,116 @@
|
||||
# 提示词:Python 智能体 / Worker 端
|
||||
|
||||
你负责与现网询价智能体 **功能等价** 的运行时。代码全新组织,不要做成单文件上帝模块。**每个模块、Handler、Graph 节点、队列/槽代码必须有详细中文注释**(文件头 + 函数职责/副作用/线程;见 `05` 注释节)。无注释不验收。
|
||||
|
||||
## 必须提供的进程
|
||||
|
||||
只允许下面这些自研进程(详见 `01` 目标进程):
|
||||
|
||||
1. **一个 HTTP**:合并现 8810/8809/8811。询价入口、H5、主账唤醒、企微应用回调。请求线程只验签、入 inbox/任务表、返回;禁止同步 LibreOffice / 等完整 LLM。
|
||||
2. **一个 Worker**:消费 LLM、识别、报价(Excel→PDF)、微盛存档。队列 + **按任务认领**(处理中/超时回收)+ 重试。并发:LibreOffice **1 槽**,其余 HTTP 类 **2~3 槽**。Windows 服务只起一份;**禁止** Redis 全局 Worker 单例锁(现网 `wecom:worker:singleton`)。
|
||||
3. **AIBOT 客户端**:连本机 8813 桥;桥进程可仍是 Node `.cjs`。
|
||||
4. 企微 inbox 消费与 outbox 外发:放在 HTTP 进程的快循环,或 Worker 里与 soffice **隔离的槽**,不得和转 PDF 串行互堵。
|
||||
|
||||
不要:独立 `bridge_api` / `wecom_robot` 端口;五个 NSSM Worker。群机器人 8812 默认不做。
|
||||
|
||||
## 禁止卡顿(必须多线程 / 多槽)
|
||||
|
||||
实现验收:**企微回调与 H5 在慢活进行时仍能秒回**;一份 PDF 不能拖死收消息、查价、出站。
|
||||
|
||||
1. **请求线程只做短事**:验签、去重、入 inbox/任务表、202/明文成功码、返回。禁止在回调 / H5 / 唤醒 HTTP 里同步 `invoke` 完整 Graph、等 LLM、跑 soffice。
|
||||
2. **尽量用多线程**:HTTP 用线程池(uvicorn workers 或等价);Worker **进程内**用线程槽并行——HTTP 类(模型、识别、主账、存档、outbox)**至少 2~3 槽**;inbox 消费与 outbox 外发独立线程,不得和转 PDF 排成一条队列。
|
||||
3. **唯一例外**:LibreOffice **1 个槽**(本机两台 soffice 会互抢卡死)。这不是「整进程单线程」。
|
||||
4. **I/O 等待要让出**:调企微、主账、TMS 经主账、对象存储、模型 HTTP 用超时 + 线程池;禁止无限阻塞、禁止热循环 `sleep` 轮询把槽占满。Graph `resume` 放在 Worker 槽里跑,不要占回调线程。
|
||||
5. **禁止用一把进程大锁串行所有工单**。防重入只锁「同一条任务 / 同一个 thread_id 的写冲突」,不同工单必须能同时跑。
|
||||
6. **共享状态要线程安全**:checkpoint、认领、outbox 用 DB 事务或按条锁,不要无锁改全局 dict。
|
||||
7. Windows 上线程优先于再开多个 Python 进程(已规定只有一个 Worker 进程)。需要并行就加槽/线程,不要再拆 NSSM。
|
||||
|
||||
卡住整机的写法一律视为缺陷,不是「先跑通再优化」。
|
||||
|
||||
## 模块边界
|
||||
|
||||
```
|
||||
NormalizedInbound
|
||||
→ 冻结只读状态快照
|
||||
→ 允许的意图集合
|
||||
→ DeepSeek A 唯一 route_decision
|
||||
→ 确定性 RouteDecision
|
||||
→ 唯一 handler
|
||||
→ 执行到下一个 wait 边界
|
||||
→ 持久化 version + 幂等键
|
||||
```
|
||||
|
||||
## 模块划分(源码,不是进程)
|
||||
|
||||
进程可以只有 HTTP + Worker;**包必须按功能切开**。现网把编排、企微业务、识别堆进超大文件,新项目禁止复现。
|
||||
|
||||
建议包(名称可改,边界不能混):
|
||||
|
||||
| 包 | 只做什么 | 不准塞什么 |
|
||||
|---|---|---|
|
||||
| `channel/wecom` | 验签、XML/JSON 解析、`sender_id`、inbox 写入 | Graph、LLM、建单 |
|
||||
| `channel/h5` | 表单上传、clarification 页 | 六态、TMS |
|
||||
| `channel/outbox` | 企微发送、限流、重试 | 抽字段 |
|
||||
| `routing` | DeepSeek A、RouteDecision | 副作用(建单/发消息) |
|
||||
| `handlers/` | 每类意图一个模块:会话、补问、建单、TMS 展示、协同、采用/调价、成交、异常 | 一个文件处理全部卡片 |
|
||||
| `graph/` | 图定义、节点各文件、pause/resume、wake | 企微 HTTP、soffice |
|
||||
| `llm/` | 网关、队列、各 mode schema | 业务六态 |
|
||||
| `jobs/` | 认领循环、识别槽、LibreOffice 槽、Archive 槽 | 回调路由 |
|
||||
| `ledger/` | 主账 HTTP 客户端 | 直连 TMS、直连 MySQL |
|
||||
| `storage/` | 对象存储 | 工单状态 |
|
||||
| `config/` | 只读环境变量 | 业务 if/else |
|
||||
|
||||
规则:
|
||||
|
||||
- 新功能先归包再写代码。入口(`main`、FastAPI `app`、Worker 启动)只组装依赖,不写业务分支。
|
||||
- Graph **节点分文件**(或按阶段分子包),禁止单文件堆全部节点。
|
||||
- Handler **一类卡片/一类意图一个文件**;公共校验放 `schema/` 或 `policy/`,不要复制粘贴进每个 handler。
|
||||
- 跨包只通过明确接口(函数/协议/事件),禁止互相 import 私有内部函数绕过边界。
|
||||
- 单文件超过约 400~600 行且已含两类职责:拆,不要继续往下加。
|
||||
|
||||
堆在一起的上帝模块一律视为缺陷,与卡顿同样不可验收。缺详细中文注释同样不可验收。
|
||||
|
||||
## 身份
|
||||
|
||||
入站已带企微 userid(`sender_id`)。禁止在收到聊天后再请求企微换 ID。无 `sender_id` 不进 Graph。工单 owner、会话、卡片权限、outbox `touser` 只用该字段。角色查主账,不查企微。H5 不从 URL 读 userid。细则见 `09`。
|
||||
|
||||
## 状态
|
||||
|
||||
| 状态 | 存储 |
|
||||
|---|---|
|
||||
| 活动工单、打断栈 | conversation session |
|
||||
| 图节点、业务上下文 | Graph checkpoint |
|
||||
| 等待点 waitVersion | suspend 账 |
|
||||
| 补问/卡片绑定 | clarification,TTL(H5 30 分钟) |
|
||||
| 正式六态 | 只调用主账 API |
|
||||
| LLM/识别/报价任务 | 各自任务表 + 认领状态(谁在做、超时释放),不是进程级单例 |
|
||||
|
||||
运行账 PostgreSQL:`PG_HOST`/`PG_DATABASE`/`PG_DSN` 走环境变量(测试 `ytd_test_runtime`,正式 `ytd_runtime`,见 `13`)。开发期间 inbox/outbox/checkpoint/任务表缺结构:**直接加迁移并执行到当前 `PG_DATABASE`**,不要问能不能加表。禁止动现网 `ytd_runtime`。
|
||||
|
||||
**LangGraph / Redis 何时用、怎么用:见 `14-LangGraph与Redis.md`。** 图:一单一个 `thread_id`,checkpoint 在 PG,停点中断,Worker 结构化 wake。Redis:`REDIS_URL`(测试 `/1` + `ytd:test:`),只做 Stream 或限流/token;checkpoint 与六态不准进 Redis。
|
||||
|
||||
## LLM
|
||||
|
||||
实现队列(Redis Stream 或 DB 任务表)、按条认领、重试、熔断、审计。不要全局 `SET NX` 单例。模式至少:
|
||||
|
||||
- `ordered_actions`(DeepSeek A,strict tool)
|
||||
- 文本字段抽取(DeepSeek B)
|
||||
- 附件文本 / 图片读取(千问)
|
||||
- 群报价抽取
|
||||
- 报价工作表映射
|
||||
|
||||
环境变量名与 `03-配置与密钥清单.md` 对齐;测试/正式取值见 `13`(`YTD_ENV`、域名、端口、库)。禁止把 `ai.ytd-scm.com` 写死在代码里。
|
||||
|
||||
## 字段
|
||||
|
||||
实现与 `inquiry-required-fields-v1.json` 等价的条件激活(JSON 放在新仓库)。SEA 箱型箱量保持单原始字段 + B 模型投影 `containerItems`。协同点击用不可变询价原话重跑 B,去重补问。
|
||||
|
||||
## 出站
|
||||
|
||||
- 主账:登录或 Token,所有写操作要幂等键(message_id / request_id / quoteVersion)。
|
||||
- 企微:只通过 outbox;失败重试;过期出站丢弃不计业务成功。询价与正式同一 Agent `1000010`;运维 `1000014`,测试告警正文加 `[test]`。
|
||||
- 对象存储:S3 兼容;生成文件后登记主账附件再发企微。
|
||||
|
||||
## 测试
|
||||
|
||||
每个业务线:完整字段不补问;缺一项只补该项;TMS 有价/无价/1003/技术失败;重复回调不建第二单。禁止依赖真实密钥才能跑单测(TMS 用 fixture 模式)。**不要**按企微 userid 在 Redis 里伪造 TMS。
|
||||
@@ -0,0 +1,81 @@
|
||||
# 提示词:工单 / TMS 主账 API
|
||||
|
||||
你负责新系统的 **业务主账**。产品决策(2026-09-12):主账以 **JeecgBoot + 低代码(Online / cgform / 代码生成器)** 为正式方式,对齐旧现网用法;库与端口走新系统(`inquiry_robot`、并存期 **8180**),禁止写现网 `jeecg-boot`。
|
||||
|
||||
决策说明见 `docs/2026-09-12-jeecg-lowcode-ledger-decision.md`。正式主账工程目录为 **`inquiry-api/`**(JeecgBoot)。
|
||||
|
||||
## 与旧项目一致的方式(已定 · 低代码)
|
||||
|
||||
- **主账工程 = JeecgBoot**(建议从旧仓 `java-backend` 拷贝后改配置,保留 `jeecg-module-inquiry`)。
|
||||
- **允许** Online / cgform / 积木报表 / 代码生成器配置询价相关表单、列表、简单 CRUD 与菜单。
|
||||
- 登录、用户、角色、菜单走 Jeecg `/sys/*` + 低代码权限模型。
|
||||
- 复杂领域(六态 transition、TMS 适配、报价版本采用/调价、智能体唤醒)可继续用手写 `jeecg-module-inquiry`(与现网「低代码 + 手写模块」混合一致);路径风格仍如 `/inquiry/workOrder/...`、`/inquiry/quotes/...`。
|
||||
- 后台以 Jeecg Vue3 为正式入口(本仓库 `inquiry-backend/`);`defHttp` + `X-Access-Token`;Nginx `/jeecgboot` → 新主账端口(`inquiry-api/`)。
|
||||
|
||||
## 模块划分
|
||||
|
||||
| 包 / 能力 | 职责 |
|
||||
|---|---|
|
||||
| Jeecg `/sys/*` + Online | 登录、菜单、字典、低代码表单/列表 |
|
||||
| `jeecg-module-inquiry`(或等价) | 工单六态、报价版本、TMS、群门禁、智能体集成等复杂规则 |
|
||||
| TMS 适配 | 密钥不出业务乱写;智能体不直连 TMS |
|
||||
|
||||
手写部分仍按领域拆分(工单 / 报价 / TMS / 人员 / 群 / 附件),不要一个上帝 Service。禁止把智能体 Graph 逻辑写进 Java。
|
||||
|
||||
类、公开方法、六态迁移、TMS 签名与投影:**详细中文 JavaDoc/块注释**。见 `05` 注释节。无注释不验收。
|
||||
|
||||
## 领域模型
|
||||
|
||||
- 工单:单号、销售企微身份、客户、业务线 SEA/AIR/LAND、陆运二级类型、六态、版本。
|
||||
- 运输段 segment:多段预留但可关闭入口。
|
||||
- 源报价(TMS 绑定)、客户报价、quoteVersion、费用行、附件元数据。
|
||||
- 群绑定:chatId、角色、与工单/段/报价版本三门禁。
|
||||
- 人员角色:wecom_id ↔ 销售/产品/运营。
|
||||
- 时间线 / 异常单 / 重试状态。
|
||||
- TMS 字典投影表:按 `tms-dictionary-projection-v2.json`。
|
||||
|
||||
## API 能力(与智能体、后台对齐)
|
||||
|
||||
- 工单:创建、校验、查询、聚合视图、六态 transition、异常 handle/retry。
|
||||
- TMS:query、template-fields、detail、health、字典 sync。lock/release 接口可留,**与现网共用 TMS 密钥期间默认关闭出站**。
|
||||
- 报价决策:采用、调价、成本/售价基线(空运与海陆规则不同,与现网语义对齐)。
|
||||
- 模板、识别任务、生成任务的查询接口(任务执行可在智能体,主账存结果指针)。
|
||||
- 智能体回调:唤醒 Graph 的事件要鉴权 `agentCallbackToken`,打到智能体**唯一 HTTP**(不要假设还存在 8809 `bridge_api`)。
|
||||
- 人员:按入站已有的 `wecom_id` 查角色;**不负责**替智能体向企微换 userid。
|
||||
|
||||
## TMS 适配器(本端独占密钥)
|
||||
|
||||
主账 HTTP **不许卡死线程池**:TMS / DB 必须有超时;接口用容器线程池处理并发请求。禁止全局锁串行所有工单。智能体唤醒回调失败要可重试,不要在 Tomcat 线程里同步等 Python Graph 跑完。
|
||||
|
||||
实现现网 TMS 网关语义:
|
||||
|
||||
- Token:`POST {base}{tokenPath}`,Basic(clientId:clientSecret),body `grantType=client_credentials`,业务码 1,缓存 accessToken。
|
||||
- 查询类:Bearer。
|
||||
- 锁舱/释放:`X-Signature` HMAC,canonical `timestamp + "\n" + nonce + "\n" + rawBody`。
|
||||
- 审计日志脱敏:token/signature/password/secret 字段打码。
|
||||
- 熔断、超时、最多 3 次、query 对 code 1/1002 短缓存。
|
||||
- `tmsEnabled=false` 时不得出站。生产现网为 `YTD_TMS_V2_ENABLED=true`。
|
||||
|
||||
路径默认:`/quote/v2/query`、`/quote/v2/detail`、`/quote/template-fields`、`/air/cabin/lock`、`/air/cabin/release`、`/auth/token`。地址与 Client 三件套、字典 Token **直接用 `03` 现网值**,不要另要一套 TMS。智能体仍只打**新主账**,不直连 TMS、不打旧 Java 8080。
|
||||
|
||||
## 字典投影
|
||||
|
||||
- EXACT_ONLY,禁止模糊。
|
||||
- 空运包装缺省可投影 `packageType=1`(全部),并保留 raw。
|
||||
- 失败要返回智能体能区分的 `source=TMS_DICTIONARY_PROJECTION` 与明确错误码,不要装成「无报价」。
|
||||
|
||||
## 不要
|
||||
|
||||
- 不要让 Python 写 MySQL 工单表。
|
||||
- 不要在主账里做自然语言抽取。
|
||||
- 不要把 Jeecg `signatureSecret` 默认值当生产密钥。
|
||||
- 后台登录与智能体服务账号分离。
|
||||
- 不要连接或 ALTER 现网 `jeecg-boot`;新系统只用 `inquiry_robot`。
|
||||
- 不要在并存期占用现网 8080;新主账用 8180(或合同约定的测试端口)。
|
||||
- 不要把无关 Jeecg 演示业务当询价主账;演示模块可删可关,Online 只配询价相关。
|
||||
|
||||
## 数据
|
||||
|
||||
MySQL 8、UTF8MB4、Asia/Shanghai。库名/用户/JDBC **全部环境变量**(`MYSQL_DB`、`MYSQL_USER`、`YTD_MYSQL_URL` 等),对照 `13`。新系统连 `inquiry_robot`,禁止连现网 `jeecg-boot`。禁止在 yml 写死库名。Redis 前缀、MinIO 桶同样走环境变量。
|
||||
|
||||
开发期间缺表、缺列、要改列:**直接写迁移并执行到当前 `MYSQL_DB`(新系统即 `inquiry_robot`)**,不要等批准。禁止动现网 `jeecg-boot`。实体/Mapper/API 与迁移同一提交。
|
||||
@@ -0,0 +1,41 @@
|
||||
# 提示词:询价管理后台
|
||||
|
||||
你负责 **新仓库** Web 管理端。产品决策(2026-09-12):后台正式方式为 **Jeecg Vue3 + Online 低代码**,与 JeecgBoot 主账一体;只打新主账(库 `inquiry_robot`、并存端口 8180),禁止连现网 8080/`jeecg-boot`。
|
||||
|
||||
详见 `docs/2026-09-12-jeecg-lowcode-ledger-decision.md`。
|
||||
|
||||
## 正式前端(Jeecg Vue)
|
||||
|
||||
- **正式入口** = Jeecg Vue3(本仓库 `inquiry-backend/`)。登录、菜单、Online 表单/列表、权限码均走 Jeecg。
|
||||
- 旧仓 `inquiry_robot/web-frontend` 与现网 Jeecg 前端仅作**对照**;新系统进程不要挂现网 8080。
|
||||
- **允许** Online / cgform / 积木报表 / 代码生成器配置询价相关生产页。
|
||||
- 复杂询价页(工单六态、TMS、报价版本)可继续用手写 `views/inquiry/*`(与现网混合模式一致)。
|
||||
- **鉴权**:`X-Access-Token`;生产 `API_URL` 同域 `/jeecgboot` → 新主账 8180(工程目录 `inquiry-api/`)。域名 `https://ai.ytd-scm.com`(见 `13`)。
|
||||
- **禁止**浏览器直连 TMS/DeepSeek/企微。
|
||||
- 仓库里若仍有独立 Ant Design Vue 实验壳,不作为正式入口。
|
||||
|
||||
## 页面(能力清单,可用 Online 或手写页实现)
|
||||
|
||||
1. 工作台:询价量、TMS 命中、报价/成交等(数字来自主账)。
|
||||
2. 工单列表/详情:六态、运输段、字段快照、TMS、客户报价版本、费用、附件、时间线。
|
||||
3. 状态操作:有权限才 transition。
|
||||
4. 人员:绑定企微 userid;销售/产品/运营。
|
||||
5. 报价模板:上传/启用/停用。
|
||||
6. 识别 / 报价生成任务:只读。
|
||||
7. 存档死信:排查。
|
||||
8. 账号/角色/菜单:Jeecg 系统管理 + Online 权限。
|
||||
|
||||
## 技术约束
|
||||
|
||||
- 详细中文注释(手写页与自定义组件)。主账加字段后台跟;业务真相在主账库,不在浏览器本地。
|
||||
- 构建产物不含 `.env` 密钥。
|
||||
|
||||
## 不要
|
||||
|
||||
- 不要把现网正在跑的 Jeecg 进程当新系统主账(端口/库必须隔离)。
|
||||
- 不要本地再存一份工单六态真相。
|
||||
- 不要做 TMS 测试开关页伪装生产。
|
||||
|
||||
## 验收
|
||||
|
||||
Jeecg Vue 登录 → Online/手写询价菜单 → 工单时间线/附件 → 无权限无操作按钮;请求进入新主账 8180 / `inquiry_robot`。
|
||||
@@ -0,0 +1,55 @@
|
||||
# 提示词:企业微信 / H5 / 存档通道
|
||||
|
||||
你负责所有「人进出系统」的通道,不负责工单六态和 TMS 签名。解析、验签、outbox、H5 token:**详细中文注释**(字段从哪来、为何快回、为何不用企微换 ID)。见 `05`。
|
||||
|
||||
## 入站来源
|
||||
|
||||
1. 应用回调(明文/密文 XML 或 JSON):挂在**智能体唯一 HTTP**(现网 8811,新系统不再单独端口)。文字、图片、文件、模板卡点击、进入会话。验签失败不入队。
|
||||
2. 群机器人:现网 8812 **默认不实现**(生产群机器人 Token 为空、走 AIBOT)。产品未书面要求不要加端口。
|
||||
3. AIBOT 长连接:独立 Node(或等价)进程听微信,转给智能体,**桥上无业务状态**,8813 仅回环。
|
||||
4. 微盛 Archive:由**后台 Worker** 轮询群消息与附件、限速下载,不要堵 HTTP 回调。
|
||||
测试与正式 H5 同一地址:`https://ai.ytd-scm.com/inquiry-form`。切流前公网仍进现网进程,见 `13`。
|
||||
|
||||
归一成内部 `InboundMessage`:tenant、org、sender_id、chat_id、chat_type、message_id、content、media、agent_id、create_time、raw。
|
||||
|
||||
## 企微身份(sender_id)
|
||||
|
||||
聊天进来 **不要再调企微接口去「获取用户 ID」**。回调 XML 的 `FromUserName`、AIBOT JSON 的发送人字段,解析后写入 `sender_id` 即可。
|
||||
|
||||
- `sender_id` 为空:不入业务队列,不建单、不回业务话术。
|
||||
- 私聊回复、模板卡 `touser`、工单销售 owner、卡片操作人、幂等键,都用 **同一条入站里的** `sender_id`。
|
||||
- 角色(销售/产品/运营)用这个 id **查主账人员表**,不是再向企微换一次 ID。
|
||||
- 群:`chat_id` + 发言人 `sender_id`;建群、拉人、@ 用报文里已有的 id。
|
||||
- H5 URL **禁止**带 userid / 工单号;身份在 clarification token 服务端绑定。
|
||||
- 通讯录同步、`user/get` 只为姓名部门展示,**不得挡**询价主路径。缺展示名可以用 userid 先跑业务。
|
||||
|
||||
`message_id` 全局去重。卡片 token 一次性、TTL、绑定 thread_id + waitVersion + 允许动作集合。inbox 按条认领处理,不要靠 Worker 进程级 Redis 单例。
|
||||
|
||||
回调必须快回(企微有超时)。验签写入 inbox 即返回;业务、模型、Graph 在其它线程消费。Archive 轮询在 Worker 槽,不占回调。禁止回调线程同步等 LLM / PDF。
|
||||
|
||||
## 出站
|
||||
|
||||
唯一出口:outbox → 企微 API。
|
||||
|
||||
能力:文本、模板卡、文件、创建群、拉人、发到指定 chat。**询价应用与正式相同 `1000010`**。运维通知 **`1000014`**。测试告警正文带 `[test]`。并存期不要改该应用回调、不要重置 Secret。
|
||||
|
||||
速率限制、重试、max age(过期不发)。Archive 席用户进群但不 @、不当报价人。
|
||||
|
||||
## 配置
|
||||
|
||||
对齐 `WECOM_*`、`WSHOTO_*`、`WECOM_AIBOT_*`、`INQUIRY_FORM_PUBLIC_BASE_URL`。明文见 `03`。CorpId `ww9c044d4227b7e574`。测试环境域名与企微 **抄正式同一套**(含 `1000010` 与 `https://ai.ytd-scm.com/wecom/callback`)。不要新建应用。
|
||||
|
||||
## H5
|
||||
|
||||
- HTTPS 公网。
|
||||
- URL 不含工单号、userid。
|
||||
- 字段列表由服务端按当前激活合同生成,提交后走与卡片相同的 clarification 动作。
|
||||
- 打开表单失败要有明确过期文案,禁止把内部异常吐给销售。
|
||||
|
||||
## 安全
|
||||
|
||||
EncodingAESKey、Callback Token、应用 Secret 只在服务器环境。回调验签失败返回错误,不入业务队列。
|
||||
|
||||
## 验收
|
||||
|
||||
用测试企业或沙箱:私聊一条完整海运 → 收到补问或报价卡;点卡不重复执行;H5 token 用一次后失效。未经授权禁止对生产客户群发。
|
||||
@@ -0,0 +1,40 @@
|
||||
# 提示词:TMS V2 对接
|
||||
|
||||
你只做主账进程内的 TMS 网关与字典投影。智能体通过主账「查价」API 间接触达 TMS。签名、投影、错误分类代码必须有**详细中文注释**(1002/1003/技术失败如何区分)。见 `05`。
|
||||
|
||||
## 认证
|
||||
|
||||
1. `client_credentials` 取 `accessToken`(Basic clientId:clientSecret)。
|
||||
2. 查询/详情/模板字段:`Authorization: Bearer`。
|
||||
3. 空运锁舱/释放:额外 HMAC 签名头,正文原字节参与签名。
|
||||
4. 生产明文见 `03`,**新系统直接复用现网 TMS 信息**(同机并行,不再另开测试 TMS):`TMS_V2_BASE_URL=http://113.106.62.254:3100/sangoe-boot`;ClientId/Secret/SignatureSecret 均为 `WVRELUFpQWdlbnQk`。`YTD_TMS_V2_ENABLED=true`。字典同步 Token 也用 `03` 现网值。凭证放新系统自己的 `.env`,不要改 `C:\yutongda\secure\` 给旧 Java 用的那份。
|
||||
|
||||
**不要**把密钥写进代码或前端。旧字段 `tmsServiceToken`/`tmsSignatureKey` 不要在 V2 再使用。
|
||||
|
||||
## 查询请求
|
||||
|
||||
主账把智能体已确认字段 + 字典投影结果映射为 TMS V2 body。投影规则以 `tms-dictionary-projection-v2.json` 为准(该文件放在新仓库):
|
||||
|
||||
- AIR:origin/destination → 机场代码;packaging → packageType
|
||||
- LAND:地址、车型、运输类型
|
||||
- SEA:港口、箱型等
|
||||
- 匹配 EXACT_ONLY;多值歧义返回 AMBIGUOUS,不得 last-write-wins
|
||||
|
||||
## 响应
|
||||
|
||||
规范化 envelope:`code`、`tmsData`、`tmsRequestId`。映射到智能体分类:
|
||||
|
||||
- code 1 且有价 → 有价
|
||||
- 1002 → 无价
|
||||
- 1003 或投影失败 → 用户/合同缺项,**不是**无价
|
||||
- HTTP 5xx/超时/熔断 → 技术失败
|
||||
|
||||
锁舱/释放:**与旧系统共用同一套 TMS Client 时,新系统默认关闭**(API 返回未开放,企微/后台不展示)。只做 query / detail / template-fields / 字典同步。切流替换旧系统前再打开 lock/release,避免两套应用抢舱。
|
||||
|
||||
## 观测
|
||||
|
||||
每次出站记录:耗时、HTTP 状态、业务码、请求摘要(无密钥)、响应摘要。连续失败熔断。字典版本号写入工单 `tmsMappingVersion`。
|
||||
|
||||
## 测试
|
||||
|
||||
用 WireMock/本地 stub:token 成功、query 1/1002/1003、签名错误、超时。禁止单测打真实 TMS。联调查价可以打现网 TMS(同一 Client);**禁止**联调 lock/release。不要做 Redis「TMS 测试开关」。无价和技术失败看真实 query 响应或 stub。
|
||||
@@ -0,0 +1,90 @@
|
||||
# 提示词:部署与运行环境
|
||||
|
||||
目标环境:甲方 **同一台** Windows Server(`129.211.181.80` / `10_206_0_15`)。现网继续跑 `C:\yutongda`。新系统是**另一套应用**,不要切旧 `ops\active-release.json`,不要占用 8080/8810/8813。现网发布仍按甲方原流程;测试环境用本目录 `12`。
|
||||
|
||||
## 同机并存
|
||||
|
||||
| 项 | 现网(不动) | 新系统 |
|
||||
|---|---|---|
|
||||
| 目录 | `C:\yutongda` | 例如 `C:\ytd-test\` |
|
||||
| 主账 / 智能体 / AIBOT | 8080 / 8810 / 8813 | 另选端口,例如 8180 / 8910 / 8913 |
|
||||
| Nginx | `ai.ytd-scm.com` | **同一域名**;切流前不改 `ai.conf` 回调/H5 |
|
||||
| MySQL / PG / Redis / MinIO | `jeecg-boot`、`ytd_runtime`、`ytd:prod:node01-07`、桶 `ytd-inquiry` | 库 `ytd_test`、`ytd_test_runtime`;Redis **db1** 前缀 `ytd:test:`;桶 `ytd-test` |
|
||||
| TMS | `03` 现网 BaseURL + Client 三件套 | **原样使用**;只 query,默认不开 lock/release |
|
||||
| 企微询价应用 | `1000010` | **同一套**,配置抄 `03` |
|
||||
| 企微运维通知 | `1000014` | **同一套** |
|
||||
|
||||
切流替换旧系统时,再把 Nginx 反代指到新端口并停现网 AIBOT 桥,企微后台回调 URL 不用改。然后停下面这份旧清单。
|
||||
|
||||
## 切流时停旧:域名与端口
|
||||
|
||||
**域名(旧站点,切流后由新系统接管同一名或下线)**
|
||||
|
||||
| 地址 | 用途 |
|
||||
|---|---|
|
||||
| `https://ai.ytd-scm.com` | 后台静态 + 总入口 |
|
||||
| `https://ai.ytd-scm.com/jeecgboot/`、`/jeecg-boot/` | 反代旧 Java 8080 |
|
||||
| `https://ai.ytd-scm.com/wecom/callback` | 企微应用回调 → 旧 8811 |
|
||||
| `https://ai.ytd-scm.com/wecom/robot/callback` | 群机器人(现网空配置)→ 旧 8812 |
|
||||
| `https://ai.ytd-scm.com/inquiry-form/` | H5 → 旧 8810 |
|
||||
| `https://ai.ytd-scm.com/inquiry-form/upload/` | H5 上传 → 旧 8810 |
|
||||
|
||||
机器公网 `129.211.181.80`、SSH `22`、Nginx `80/443` **不要关**(新系统还要用)。`www.waxonai.cn` 只是仓库里旧示例 conf,生产以 `ai.ytd-scm.com` 为准。
|
||||
|
||||
**本机进程口(停旧应用服务)**
|
||||
|
||||
| 端口 | 旧进程 | 切流后 |
|
||||
|---|---|---|
|
||||
| 8080 | Java JeecgBoot | 停 |
|
||||
| 8809 | Python bridge_api | 停 |
|
||||
| 8810 | Python agent_api | 停 |
|
||||
| 8811 | Python wecom_callback | 停 |
|
||||
| 8812 | Python wecom_robot | 停(若在跑) |
|
||||
| 8813 | AIBOT 仅 127.0.0.1 | 停 |
|
||||
| (无端口) | wecom/llm/recognition/quote/archive Worker | 停 NSSM |
|
||||
|
||||
**不要当「旧询价服务」关掉的**
|
||||
|
||||
| 地址 | 原因 |
|
||||
|---|---|
|
||||
| 数据机 `10.206.0.14:3306/5432/6379` | 实例共用;只停用库 `jeecg-boot`、`ytd_runtime` 与前缀 `ytd:prod:node01-07` |
|
||||
| 本机 MinIO `9000` / 控制台 `9001` | 实例共用;只停用桶 `ytd-inquiry` |
|
||||
| TMS `http://113.106.62.254:3100/sangoe-boot` | 外部系统,新系统继续用 |
|
||||
| Gitea `gitea.lionqi.com` | 源码,无关运行 |
|
||||
|
||||
企微侧切流:后台 `1000010` 回调地址保持 `https://ai.ytd-scm.com/wecom/callback`,只改 Nginx 指到新智能体。停现网 8813 后再起新 AIBOT(同一 Bot)。运维 **`1000014` 仍共用**。测试告警正文带 `[test]`。
|
||||
|
||||
## 必须保留的运维原则
|
||||
|
||||
1. 制品不可变:新版本写入 `releases\` 新目录,禁止覆盖活动目录。
|
||||
2. 原子切换指针:`ops\active-release.json` 等;失败自动回指旧版。
|
||||
3. 互斥锁:禁止两人同时部署。
|
||||
4. 构建不含 `.env`、密钥、日志、用户附件、数据库 dump。
|
||||
5. 健康检查 ≠ 业务验收。
|
||||
6. 并存阶段:禁止真实 TMS **lock/release**、禁止改现网回调与防火墙、禁止改 `C:\yutongda\secure\`。查价可用现网 TMS。测试库 `ytd_test` / `ytd_test_runtime` 的加表加字段按 `05` 直接迁移,不必等批准。
|
||||
|
||||
## 进程与端口
|
||||
|
||||
新系统自己监听(避开现网):**8180** 主账、**8910** 智能体 HTTP、**8913** AIBOT 回环、一个 Worker。现网 8080/8810/8813 保持原样。
|
||||
|
||||
旧 release 的 8809/8811/8812 以及五个旧 Worker:**切流前不要停**。新系统用自己的服务名与端口。发布新版本时停的是 `C:\ytd-test\` 里的旧号,不是 `C:\yutongda`。切流时才把 `ai.conf` 的 inquiry-form / wecom/callback 反代到新 HTTP 端口。不要 Redis 全局单例锁。
|
||||
|
||||
## 基础设施
|
||||
|
||||
本机/服务器安装:JDK(若仍用 Java)、Python 3.12、Node(AIBOT 桥)、MySQL、PostgreSQL、Redis、MinIO 或 S3、LibreOffice、Nginx。
|
||||
|
||||
域名 `ai.ytd-scm.com` TLS 终止在 Nginx:静态后台、反代 `/jeecgboot`、inquiry-form 与企微回调到智能体 HTTP。
|
||||
|
||||
## 环境文件
|
||||
|
||||
- 示例:仓库 `.env.example` 只有变量名。
|
||||
- 生产:服务器本地文件,权限仅运行账号。明文对照 `03`。
|
||||
- 本机开发:用脚本注入环境变量,关闭真实出站。
|
||||
|
||||
## 你要交付的脚本
|
||||
|
||||
等价于现网:远程身份检查、累计发布、发布后 status、远程 PowerShell 封装。不要发明「scp 覆盖几个 py」的热修当正式发布。
|
||||
|
||||
## SSH
|
||||
|
||||
用户 `ytd_extdev_0903`,Ed25519,`IdentityFile ~/.ssh/id_ed25519_ytd`。公钥指纹见 `03`。私钥永不进仓库。
|
||||
@@ -0,0 +1,92 @@
|
||||
# 提示词:测试环境部署(同机并存)
|
||||
|
||||
你只部署 **测试环境**。现网继续跑。不要按现网累计发布器去切 `C:\yutongda`。现网密钥对照 `03`,进程形态见 `01`/`11`,环境对照见 `13`。
|
||||
|
||||
机器与现网同一台:公网 `129.211.181.80`,主机名 `10_206_0_15`,SSH `ytd_extdev_0903`,指纹见 `03`。私钥优先 `~/.ssh/id_ed25519_ytd`。出口白名单不变。不得输出私钥和 Secret。
|
||||
|
||||
## 现网禁止触碰
|
||||
|
||||
- 目录:`C:\yutongda`、`releases\`、`ops\active-release*.json`
|
||||
- 端口:8080、8809、8810、8811、8813 必须保持监听
|
||||
- 站点:`https://ai.ytd-scm.com` 及 `/wecom/callback`、`/inquiry-form`(Nginx 反代目标切流前不准改)
|
||||
- 库:`jeecg-boot`、`ytd_runtime`;Redis `ytd:prod:node01-07`;桶 `ytd-inquiry`
|
||||
- 企微询价应用 `1000010` 的后台设置(不要重置 Secret、不要改回调 URL)
|
||||
- 脚本:禁止对现网执行 `Deploy-YtdCumulativeRelease.ps1`
|
||||
- 禁止改 `C:\yutongda\secure\`、现网 `.env`、现网 `ai.conf` 已有 location
|
||||
|
||||
## 测试环境落点
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 运行根 | `E:\wwwroot`(`admin\current` / `agent\current`) |
|
||||
| 主账 | **8180** |
|
||||
| 智能体 HTTP | **8910**(H5 + 企微回调 + 主账唤醒,一个进程) |
|
||||
| AIBOT | **8913** 仅 127.0.0.1 |
|
||||
| Worker | 无对外端口;LibreOffice 1 槽,HTTP 类 2~3 槽 |
|
||||
| MySQL | 库/用户 `inquiry_robot`(数据机 `10.206.0.14:3306`,口令新开) |
|
||||
| PostgreSQL | 库/用户 `inquiry_robot_runtime` |
|
||||
| Redis | db1,前缀 `inquiry_robot:` |
|
||||
| MinIO | 桶 `inquiry_robot`(实例仍 9000) |
|
||||
|
||||
不要开 8809/8811/8812。不要 Redis 全局单例锁。Nginx 80/443、SSH 22、3306/5432/6379、9000 不要关。
|
||||
|
||||
`MYSQL_*` / `PG_*` / `REDIS_URL`(**db1**)/ `REDIS_KEY_PREFIX=inquiry_robot:` / `OBJECT_STORAGE_BUCKET=inquiry_robot` 完整对照见 `13`。口令新开,勿把旧现网 `MYSQL_PASSWORD`/`PG_PASSWORD` 写进新系统 `.env`。
|
||||
|
||||
## 域名与企微(与正式相同)
|
||||
|
||||
测试 **不另开域名、不另申请证书、不新建企微应用、不新建智能机器人**。
|
||||
|
||||
从 `03` 原样抄入测试 `.env`:`WECOM_AGENT_ID=1000010`、Secret、Callback Token、EncodingAESKey、`WECOM_CALLBACK_URL=https://ai.ytd-scm.com/wecom/callback`、`INQUIRY_FORM_PUBLIC_BASE_URL=https://ai.ytd-scm.com/inquiry-form`、AIBOT BotId/Secret、运维 `1000014`。可信域名已是 `ai.ytd-scm.com`,不用再配。
|
||||
|
||||
**并存期:** 不要改 `ai.conf`,公网回调和 H5 仍进现网。测试用本机 `8910` 联调。`WECOM_AIBOT_ENABLED` 默认关,避免和现网 8813 抢长连接。要用企微真收消息验收新系统 = 切流(改 Nginx 反代 + 停现网 AIBOT 再起 8913),现网会暂停收询价。
|
||||
|
||||
```text
|
||||
YTD_ENV=test
|
||||
WECOM_CALLBACK_URL=https://ai.ytd-scm.com/wecom/callback
|
||||
INQUIRY_FORM_PUBLIC_BASE_URL=https://ai.ytd-scm.com/inquiry-form
|
||||
BIZ_API_BASE_URL=http://127.0.0.1:8180/jeecg-boot
|
||||
AGENT_CALLBACK_BASE_URL=http://127.0.0.1:8910
|
||||
WECOM_AIBOT_BRIDGE_URL=http://127.0.0.1:8913
|
||||
WECOM_AIBOT_INGRESS_URL=http://127.0.0.1:8910/internal/aibot/inbound
|
||||
```
|
||||
|
||||
前端 `VITE_GLOB_API_URL=/jeecgboot`,`VITE_GLOB_DOMAIN_URL=https://ai.ytd-scm.com`。不要加 `ai-test.conf`。
|
||||
|
||||
## TMS
|
||||
|
||||
现网 BaseURL + Client 三件套(`03`)。只 QUERY / 详情 / 字典。默认关闭 LOCK/RELEASE。智能体只打测试主账 8180,不直连 TMS、不打现网 8080。
|
||||
|
||||
## 库表(测试库可直接改)
|
||||
|
||||
开发需要加表、加字段、改字段时:**直接对 `inquiry_robot` / `inquiry_robot_runtime` 做版本化迁移**,不必先等 Task 批准。
|
||||
|
||||
仍须批准的:改现网库、改现网 Secret、TMS LOCK/RELEASE、对非测试人员发企微。
|
||||
|
||||
## 发布原则
|
||||
|
||||
1. 新版本写入 `E:\wwwroot\` 的 `agent\releases` / `admin\releases`,再切 `current` 联接;禁止覆盖正在跑的 current 目标目录内容(先发 release 再切联接)。
|
||||
2. 用测试自己的指针;失败回指上一测试版本。
|
||||
3. 先停 **测试** 旧进程再起新的;禁止停现网服务。
|
||||
4. 禁止 scp 几个文件当正式发布。
|
||||
5. 构建不含 `.env`、密钥、日志、用户附件、dump。
|
||||
6. 健康检查 200 ≠ 业务验收。
|
||||
|
||||
## 部署前必须同时成立
|
||||
|
||||
- 现网 8080、8810、8813 仍在听
|
||||
- 本次目标是 8180/8910/8913
|
||||
- 未改 `C:\yutongda\ops\` 活动指针
|
||||
|
||||
误停现网端口或改了现网指针:立即停手,先恢复现网,再报告。
|
||||
|
||||
## 未经 Task 批准不得
|
||||
|
||||
- TMS LOCK/RELEASE(QUERY 按任务批准)
|
||||
- 给测试可见范围以外的人或生产客户群发企微
|
||||
- 写现网库
|
||||
- 改现网 Secret、防火墙、`1000010` 回调
|
||||
- Git 强推
|
||||
|
||||
## 汇报
|
||||
|
||||
Task、分支 commit、测试目录与端口、是否误碰 `C:\yutongda`(必须为否)、现网端口仍监听、TMS/企微次数、回滚点、尚未完成的企微 fresh 验收。
|
||||
@@ -0,0 +1,119 @@
|
||||
# 旧现网 vs 新系统 inquiry_robot(切换只改配置,不改代码)
|
||||
|
||||
同一套制品。用 `YTD_ENV=prod` 或 `YTD_ENV=test` 区分阶段(变量名仍叫 YTD_*,与 `03` 对齐)。
|
||||
**域名与企微与现网相同**(`ai.ytd-scm.com`、应用 `1000010`)。
|
||||
**新系统资源名一律 `inquiry_robot*`**,禁止再用 `ytd_test` / `ytd:test:` / `ytd-test`。
|
||||
禁止在代码里写死域名/库名。
|
||||
|
||||
切流目标(方案 B):`E:\wwwroot` 取代 `C:\yutongda`。清单见 `deploy/CUTOVER-TO-PROD.md`。
|
||||
|
||||
对照表是切换清单。旧现网发布仍走甲方原流程与 `C:\yutongda` 指针;新系统只写 `E:\wwwroot`。
|
||||
|
||||
## 对照
|
||||
|
||||
| 项 | 旧现网(仍在跑) | 新系统 `inquiry_robot` |
|
||||
|---|---|---|
|
||||
| `YTD_ENV` | `prod`(旧进程) | 切流前可用 `test`;切流日改 `prod` |
|
||||
| 公网域名 | `ai.ytd-scm.com` | **同一域名** |
|
||||
| DNS / 证书 / Nginx | 已有 `ai.conf` | **不要另开域名/证书**;反代按切流改 |
|
||||
| 站点 / H5 / 企微回调 | 同左 | 配置字符串相同;企微回调 URL **不用改** |
|
||||
| 后台 API 前缀 | `/jeecgboot` → 8080 | `/jeecgboot` → **新主账 8180**(切流后) |
|
||||
| 运行根 | `C:\yutongda` | **`E:\wwwroot`**(`admin\current` / `agent\current`) |
|
||||
| 主账端口 | 8080(Jeecg) | **8180**(新 Java 主账,非 Jeecg) |
|
||||
| 智能体 HTTP | 8810(另 8809/8811) | **8910**(合并) |
|
||||
| AIBOT | 8813 | **8913**(切流前勿双连) |
|
||||
| MySQL | `jeecg-boot` / `ytd_jeecg` | **`inquiry_robot` / `inquiry_robot`** |
|
||||
| PostgreSQL | `ytd_runtime` | **`inquiry_robot_runtime`** |
|
||||
| Redis | db0 `ytd:prod:node01-07` | db1 **`inquiry_robot:`** |
|
||||
| MinIO 桶 | `ytd-inquiry` | **`inquiry-robot`**(S3 桶名不能用下划线) |
|
||||
| 询价企微应用 | `1000010` | **同一套** |
|
||||
| 运维企微 | `1000014` | **同一套**;切流前告警可加 `[test]` |
|
||||
| AIBOT Bot | 现网 Bot | **同一套**;切流先停 8813 再开 8913 |
|
||||
| TMS | `03` 现网 Client | 同一套;切流前默认关 lock/release |
|
||||
| 发布脚本 | 现网累计发布器 | 只写 `E:\wwwroot` |
|
||||
| 告警前缀 | 无 | 切流前 `[test]`;切流后去掉 |
|
||||
|
||||
数据机 IP、3306/5432/6379、MinIO `127.0.0.1:9000` **两边相同**。只换库名、用户、Redis db/前缀、桶。
|
||||
|
||||
## 数据库与存储(同一套变量名)
|
||||
|
||||
代码、YAML 只读变量名,**禁止**写死库名。旧现网明文见 `03`;新系统口令新开,写入 `E:\wwwroot\.env`。
|
||||
|
||||
| 变量 | 旧现网 | 新系统 |
|
||||
|---|---|---|
|
||||
| `MYSQL_HOST` | `10.206.0.14` | 同左 |
|
||||
| `MYSQL_PORT` | `3306` | 同左 |
|
||||
| `MYSQL_DB` | `jeecg-boot` | **`inquiry_robot`** |
|
||||
| `MYSQL_USER` | `ytd_jeecg` | **`inquiry_robot`** |
|
||||
| `MYSQL_PASSWORD` | 见 `03` | **新开,勿抄旧现网** |
|
||||
| `YTD_MYSQL_URL` / JDBC | `.../jeecg-boot?...` | `.../inquiry_robot?...` |
|
||||
| `PG_HOST` | `10.206.0.14` | 同左 |
|
||||
| `PG_PORT` | `5432` | 同左 |
|
||||
| `PG_DATABASE` | `ytd_runtime` | **`inquiry_robot_runtime`** |
|
||||
| `PG_USER` | `ytd_runtime` | **`inquiry_robot_runtime`** |
|
||||
| `PG_PASSWORD` | 见 `03` | **新开** |
|
||||
| `PG_SSLMODE` | `prefer` | `prefer` |
|
||||
| `CHECKPOINT_BACKEND` | `postgres` | `postgres` |
|
||||
| `YTD_REDIS_HOST` | `10.206.0.14` | 同左 |
|
||||
| `YTD_REDIS_PORT` | `6379` | 同左 |
|
||||
| `YTD_REDIS_USERNAME` | `ytd_app` | 可同账号或新账号 |
|
||||
| `REDIS_URL` | `...6379/0` | **`...6379/1`** |
|
||||
| `REDIS_KEY_PREFIX` | `ytd:prod:node01-07` | **`inquiry_robot:`** |
|
||||
| `OBJECT_STORAGE_BUCKET` | `ytd-inquiry` | **`inquiry-robot`** |
|
||||
|
||||
新系统 `.env` 片段(口令留空):
|
||||
|
||||
```text
|
||||
YTD_ENV=test
|
||||
YTD_DEPLOY_ROOT=E:\wwwroot
|
||||
MYSQL_DB=inquiry_robot
|
||||
MYSQL_USER=inquiry_robot
|
||||
YTD_MYSQL_URL=jdbc:mysql://10.206.0.14:3306/inquiry_robot?characterEncoding=UTF-8&useUnicode=true&useSSL=true&requireSSL=true&verifyServerCertificate=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
PG_DATABASE=inquiry_robot_runtime
|
||||
PG_USER=inquiry_robot_runtime
|
||||
REDIS_URL=redis://ytd_app:<密码>@10.206.0.14:6379/1
|
||||
REDIS_KEY_PREFIX=inquiry_robot:
|
||||
OBJECT_STORAGE_BUCKET=inquiry-robot
|
||||
```
|
||||
|
||||
**切换环境 = 换 `.env` 取值,不改代码、不在迁移里写死库名。**
|
||||
|
||||
切流前新进程不得连 `jeecg-boot` / `ytd_runtime` / Redis `/0` 且前缀 `ytd:prod:` / 桶 `ytd-inquiry`。
|
||||
|
||||
## 代码约定
|
||||
|
||||
所有环境差异只进 `.env` / 前端构建参数 / Nginx,例如:
|
||||
|
||||
```text
|
||||
YTD_ENV=test
|
||||
PUBLIC_BASE_URL=https://ai.ytd-scm.com
|
||||
WECOM_CALLBACK_URL=https://ai.ytd-scm.com/wecom/callback
|
||||
INQUIRY_FORM_PUBLIC_BASE_URL=https://ai.ytd-scm.com/inquiry-form
|
||||
BIZ_API_BASE_URL=http://127.0.0.1:8180
|
||||
AGENT_CALLBACK_BASE_URL=http://127.0.0.1:8910
|
||||
WECOM_AIBOT_BRIDGE_URL=http://127.0.0.1:8913
|
||||
WECOM_AIBOT_INGRESS_URL=http://127.0.0.1:8910/internal/aibot/inbound
|
||||
REDIS_KEY_PREFIX=inquiry_robot:
|
||||
PG_DATABASE=inquiry_robot_runtime
|
||||
MYSQL_DB=inquiry_robot
|
||||
OBJECT_STORAGE_BUCKET=inquiry_robot
|
||||
```
|
||||
|
||||
两套 `.env` 分开放:旧现网仍在 `C:\yutongda\...`,新系统在 `E:\wwwroot\.env`。不要互相覆盖。
|
||||
|
||||
## 以后切到正式(新系统接管)
|
||||
|
||||
见 `deploy/CUTOVER-TO-PROD.md`。顺序摘要:
|
||||
|
||||
1. 新进程在隔离库 `inquiry_robot*` 验收通过。
|
||||
2. `.env`:`YTD_ENV=prod`;库继续 `inquiry_robot*`(或甲方最终名)。
|
||||
3. Nginx 反代切到新主账/智能体;企微回调 URL 不用改。
|
||||
4. 停旧 8813,再起 8913。
|
||||
5. 去掉告警 `[test]`。
|
||||
|
||||
## 禁止
|
||||
|
||||
- 新进程连 `jeecg-boot` / `ytd:prod:` / 桶 `ytd-inquiry`
|
||||
- 新系统再使用 `ytd_test` / `ytd:test:` / `ytd-test` 命名
|
||||
- 并存期与现网 **同时** 连接同一 AIBOT 长连接
|
||||
- 一份 `.env` 混用两套库
|
||||
@@ -0,0 +1,127 @@
|
||||
# LangGraph 与 Redis:何时用、怎么用
|
||||
|
||||
给新项目实现用。可以换等价库,语义必须对齐。环境变量与 db/前缀见 `03`、`13`。
|
||||
|
||||
---
|
||||
|
||||
## 一、LangGraph 什么情况下用
|
||||
|
||||
**用:** 一条询价要多次停下来等人、等卡片、等主账、等 Worker 文件,然后从精确断点继续。
|
||||
|
||||
典型停点:补问字段、等建单结果、等 TMS 分类后的销售选择、等协同/群报价、等采用/调价、等 Excel/PDF、等成交/未成交。
|
||||
|
||||
**不用:**
|
||||
|
||||
| 事情 | 谁做 |
|
||||
|---|---|
|
||||
| 企微验签、inbox、解析 `sender_id` | 通道 HTTP / inbox |
|
||||
| 意图(新询价 / 点卡 / 继续本单) | DeepSeek A |
|
||||
| 抽字段、读图、读表 | DeepSeek B / 千问(经 LLM 队列) |
|
||||
| 工单六态、报价版本真相 | 主账 MySQL |
|
||||
| TMS HTTP | 主账适配器 |
|
||||
| 转 PDF、写对象存储 | Worker LibreOffice 槽 |
|
||||
|
||||
自然语言进模型;图节点只编排和调用。节点里不准正则猜字段、不准用图状态假装主账已成功。
|
||||
|
||||
没有「等人/等文件」的一次性工具调用,不要硬套 Graph。
|
||||
|
||||
---
|
||||
|
||||
## 二、LangGraph 怎么用
|
||||
|
||||
1. **一张状态图**
|
||||
节点对应业务步(解析/补问 → 建单 → 查价 → 协同 → 报价 → 采用/调价 → 成交)。停靠点(补问、等卡、等文件、等群)设为中断(现网 `interrupt_before` 一组 `pause_*`)。
|
||||
|
||||
2. **一条询价一个 `thread_id`**
|
||||
绑会话/工单。新开询价新 thread;旧单 `resume` 精确断点。禁止拿新消息重放已提交的建单/查价。
|
||||
|
||||
3. **Checkpointer 在 PostgreSQL**
|
||||
正式旧现网:`ytd_runtime`。新系统:`inquiry_robot_runtime`。进程重启后按 `thread_id` 捞图。不要把 checkpoint 放 Redis。
|
||||
|
||||
4. **谁启动图**
|
||||
- 入站 → DeepSeek A →「继续本单」→ `invoke` / `resume`。无 `sender_id` 不进图。
|
||||
- Worker 做完识别或 PDF → **结构化 wake**(工单号、quoteVersion、waitVersion)。用户聊天文字不能冒充「文件已生成」。
|
||||
|
||||
5. **waitVersion + 卡片**
|
||||
补问卡、采用卡绑 `thread_id + waitVersion + 允许动作`。过期或错版本点击丢弃。H5 TTL 30 分钟。
|
||||
|
||||
6. **与主账边界**
|
||||
图可记「准备建单、TMS 结果分类」;六态成功只认主账 API。图成功、主账失败 → 未报价。
|
||||
|
||||
7. **会话与图分工**
|
||||
活动工单、打断栈 → conversation session;节点与业务上下文 → checkpoint;等待点 → suspend 账。不要在图里再做第二套六态机。
|
||||
|
||||
现网参考形态:`StateGraph` + Postgres checkpointer + `thread_id` + 中断停靠。新项目可用 LangGraph 或等价状态机,但必须有:停点、checkpoint、按版本唤醒、禁止用户文字假冒 Worker。
|
||||
|
||||
---
|
||||
|
||||
## 三、Redis 什么情况下用
|
||||
|
||||
**用:** 短命、可丢、可重建的协调。重启丢几秒可以接受。
|
||||
|
||||
| 用途 | 说明 |
|
||||
|---|---|
|
||||
| LLM / 识别任务队列 | Stream(或 DB 任务表二选一,见下);入口只入队,Worker 认领执行 |
|
||||
| 短幂等 | 同一 `idempotency_key` 短 TTL 内不重复入队 |
|
||||
| 企微 access_token 缓存 | 避免每次打企微;挂了可回内存再拉 |
|
||||
| 出站 / API 限流 | 窗口计数;超限拒绝或排队,不改工单态 |
|
||||
| 热缓存 | 只读加速;没有也能从 PG/MySQL 算出 |
|
||||
|
||||
**不用 Redis 当:**
|
||||
|
||||
- 工单六态、报价版本、权限(主账)
|
||||
- Graph checkpoint、suspend、waitVersion、inbox/outbox 持久账(PostgreSQL)
|
||||
- 附件字节(对象存储)
|
||||
- Worker 进程全局单例锁(现网 `wecom:worker:singleton` / `SET NX`,新系统禁止)
|
||||
- 按企微 userid 伪造 TMS 无价/异常(现网测试开关,新系统禁止)
|
||||
|
||||
真相在库里。Redis 挂了:队列可积压、限流失效、token 重拉;**已建单、已报价、已成交不得丢。**
|
||||
|
||||
---
|
||||
|
||||
## 四、Redis 怎么用
|
||||
|
||||
1. **连接**
|
||||
只用 `REDIS_URL` + `REDIS_KEY_PREFIX`(或代码里统一前缀函数)。
|
||||
旧现网:db0,前缀 `ytd:prod:…`。新系统:db1,前缀 `inquiry_robot:`。禁止新进程写旧现网前缀。
|
||||
|
||||
2. **键必须带环境前缀**
|
||||
所有 key:`{REDIS_KEY_PREFIX}:…`。LLM 队列 namespace 也要能随环境错开,避免测服抢走现网任务。
|
||||
|
||||
3. **队列(若用 Stream)**
|
||||
- `XADD` 入队,消费者组 `XREADGROUP`。
|
||||
- **按条认领**:PEL + 租约心跳;Worker 挂了超时回收,别的槽再做。
|
||||
- 结果短 TTL(现网约任务 300s / 结果 900s 量级,新项目可配)。
|
||||
- HTTP 回调线程禁止同步等到完整 LLM(禁止 `wait_result` 堵在请求线程);只入队或写 PG 任务表后返回,由 **其它线程槽** 消费。不同任务并行认领,不要一个线程串行全部 Stream。
|
||||
- 同一条消息防重入靠任务认领,不靠「全机只有一个 Worker」的 Redis 锁。
|
||||
|
||||
4. **也可以不用 Stream**
|
||||
LLM/识别/报价任务可以全部落 PG 任务表 + 认领字段。Redis 则只留 token 缓存和限流。二选一写进设计;不要 Stream 和表双写两套真相。
|
||||
|
||||
5. **限流**
|
||||
按 scope(全局 / 用户 / 出站)滑动或固定窗口。超限返回可重试,不写主账失败。
|
||||
|
||||
6. **Token 缓存**
|
||||
GET 未命中再调企微;SET 带过期。失败回退再请求,不要把业务打成「未认证工单」。
|
||||
|
||||
7. **TTL**
|
||||
队列结果、幂等、限流、token 都要过期。没有 TTL 的业务事实不要进 Redis。
|
||||
|
||||
8. **同机并存**
|
||||
与现网共用 `10.206.0.14:6379`,**必须换 db 和前缀**。不要 `FLUSHDB`/`FLUSHALL`。
|
||||
|
||||
---
|
||||
|
||||
## 五、对照(实现时贴在旁边)
|
||||
|
||||
| 问题 | 放哪 |
|
||||
|---|---|
|
||||
| 这条询价跑到哪一节点 | Graph checkpoint(PG) |
|
||||
| 能不能点这张卡 | waitVersion + clarification(PG) |
|
||||
| 工单是不是已报价 | 主账六态(MySQL) |
|
||||
| 下一个 LLM 任务谁做 | Redis Stream 或 PG 任务表认领 |
|
||||
| 会不会把企微打爆 | Redis 限流 |
|
||||
| 会不会两个进程抢同一条 inbox | 任务认领 + 超时回收;服务只起一份 |
|
||||
| Worker 能不能双开 | Windows 服务一份 + 发布先停再起;**禁止** Redis 全局单例 |
|
||||
|
||||
LangGraph = 剧本和书签。Redis = 传话和限速。企微 = 舞台。主账 = 账本。模型 = 台词。
|
||||
Reference in New Issue
Block a user