

项目本质是一个**"前端对话入口 + FastAPI编排层 + 技能执行层"**的 AI/自动化平台,近几次迭代已经从"纯通用内容生成"偏向了 JD MKU/行云业务自动化。
总体框架
- 前端:
Vue 3 + Vue Router + Element Plus + Axios + Vite - 后端:
FastAPI + Pydantic + SQLAlchemy - 编排/智能层:
LangGraph + LangChain Agent(可选) - 数据层:
MySQL(历史记录) + Redis(缓存) + Milvus(知识检索) - 容错策略:MySQL/Redis/Milvus/LLM 都支持"不可用降级",核心接口仍可返回结果
调用逻辑(主链路)
1) 前端到后端
前端统一通过 frontend/src/api/index.js 调 /api/*:
POST /api/chat:自然语言入口(主入口)POST /api/generate-material:直接指定 skill 执行GET /api/skills:拉技能列表POST /api/refresh-cookie:触发 Playwright 刷新登录态GET /api/cookie-status:检查 Cookie 是否可用
前端在 MainLayout.vue/ChatView.vue/MaterialView.vue 中都做了同一类处理:
如果后端返回 MKU_COOKIE_* 或 INTEST_COOKIE_*,会自动先调 refresh-cookie 再重试业务请求。
2) FastAPI 路由层
backend/app.py 初始化应用并挂载 backend/api/routes.py 到 /api。
routes.py 是控制器层,做三件事:
- 收参数(Pydantic Model)
- 调服务层(
workflow_engine/tool_executor) - 可选落库历史(MySQL 不可用则跳过,不阻断主流程)
3) /chat 的核心编排(最关键)
/chat -> workflow_engine.execute(message),在 workflow_engine.py 内是一个 LangGraph 三节点流程:
parse_requirementexecute_skillsaggregate_results
但当前实现里,parse_requirement 已经调用 llm_scheduler.parse_and_execute() 并通常直接得到结果;
execute_skills 节点多数情况下不会再次执行(除非前一步失败且有可执行 skill 列表)。
也就是说:图结构是三段式,实际运行常是"第一段直接产出结果 + 第三段聚合/缓存"。
4) LLMScheduler 的决策机制
backend/services/llm_scheduler.py 是"路由大脑",优先级大致如下:
- MKU/行云相关请求优先走规则分支(避免 LLM 超时)
- 若非上述且 Agent 可用,走
LangChain OpenAI Functions Agent - 若无可用 LLM,则走
_simple_parse关键词规则匹配
规则分支里内置了大量业务意图解析,例如:
- 更新 MKU/行云 Cookie
- "根据 SKU 创建商机预占 MKU"
- "根据行云 skuId 创建 mkuId"
- "固定 SKU 创建 MKU"
这些会直接委托给 mku_agent 或 xingyun_mku_agent,再落到具体 JD skill 执行。
5) Skill 执行层
backend/services/tool_executor.py 维护一个 skills 注册表:
- 通用技能:
material_generation/compliance_check/api_call/knowledge_retrieval - JD业务技能:
jd_mku_publish/jd_mku_submit_task/jd_create_mku_by_sku/jd_batch_add_sku等 - Cookie状态技能:
check_mku_cookie_status/check_intest_cookie_status
所有 skill 统一继承 BaseSkill,通过 execute(**kwargs) 返回标准结构。
数据与状态管理逻辑
- Redis:
workflow:{md5(user_input)}缓存/chat结果,默认 1 小时 - MySQL:记录历史请求与响应;如果不可用,
get_db()返回None,接口继续可用 - Milvus:仅用于
knowledge_retrieval,无连接时返回空或模拟结果 - Cookie:
cookie_store.py多级回退读取:- 运行时内存
.envconfig.ini/config/credentials/*.txt
这让 MKU/行云链路对"手工粘 Cookie"依赖降低很多。
前后端协作特点(你这个项目比较有特色的点)
- 不是典型"前端只发问,后端全靠 LLM",而是:
- 业务特化规则优先
- LLM 是可选增强,不是唯一入口
- 前端已经内建"Cookie失效 -> 自动刷新 -> 自动重试"闭环
- 后端多数基础组件都做了降级,系统韧性不错
框架层面评价(简短)
-
优点
- 分层清楚:API 层 / 编排层 / 技能层 / 数据层
- 兼顾 AI 与传统规则,工程可控性高
- 对外部依赖故障容忍度高(DB/Redis/Milvus/LLM)
-
当前实现上的一个现实情况
ARCHITECTURE.md仍偏"通用内容平台"叙述;代码已经明显偏向 MKU/行云自动化,文档有些滞后。

模块框架图

md
AI Platform Architecture Diagrams
本文档整理项目核心架构图,覆盖分层、模块依赖和两条主要调用链路,便于研发、联调和排障时快速定位。
1) 总体分层图(业务视角)
```mermaid
flowchart TB
U[用户/浏览器] --> FE[前端 Vue3 + Element Plus]
FE --> API[FastAPI API层]
subgraph Frontend
FE1[MainLayout / ChatView / MaterialView]
FE2[Axios /api]
FE3[Cookie自动刷新逻辑]
FE1 --> FE2
FE1 --> FE3
end
FE --> FE1
subgraph Backend["后端(ai-platform/backend)"]
API --> R1["/api/chat"]
API --> R2["/api/generate-material"]
API --> R3["/api/skills /health /cookie-status /refresh-cookie"]
R1 --> WF[WorkflowEngine<br/>LangGraph]
WF --> P1[parse_requirement]
WF --> P2[execute_skills]
WF --> P3[aggregate_results]
P1 --> LLM[LLMScheduler]
LLM -->|MKU/行云关键词| RULE[规则路由]
LLM -->|可用时| AGENT[LangChain Agent]
LLM -->|降级| SIMPLE[简单关键词匹配]
RULE --> MKUAgent[mku_agent / xingyun_mku_agent]
AGENT --> EXEC[ToolExecutor]
SIMPLE --> EXEC
MKUAgent --> EXEC
P2 --> EXEC
R2 --> EXEC
R3 --> COOKIE[Cookie Store + Playwright刷新脚本]
end
subgraph Skills["技能层(Skills)"]
EXEC --> S1[material_generation]
EXEC --> S2[compliance_check]
EXEC --> S3[api_call]
EXEC --> S4[knowledge_retrieval]
EXEC --> S5[jd_mku_publish / jd_mku_submit_task / jd_create_mku_by_sku ...]
end
subgraph Data["数据层"]
WF <--> REDIS[(Redis 缓存)]
API <--> MYSQL[(MySQL 历史记录)]
S4 <--> MILVUS[(Milvus 向量检索)]
COOKIE <--> CONF[.env / config.ini / credentials]
end
FE3 --> R3
```
2) 文件级依赖图(工程视角)
```mermaid
flowchart LR
subgraph F["frontend/src"]
A1["main.js"]
A2["App.vue"]
A3["router/index.js"]
A4["api/index.js (axios: /api)"]
A5["views/MainLayout.vue"]
A6["views/ChatView.vue"]
A7["views/MaterialView.vue"]
A8["utils/cookieRefresh.js"]
end
A1 --> A2 --> A3
A5 --> A4
A6 --> A4
A7 --> A4
A5 --> A8
A6 --> A8
A7 --> A8
subgraph B["backend"]
B1["run.py"]
B2["app.py (FastAPI app)"]
B3["api/routes.py"]
end
B1 --> B2 --> B3
A4 -->|HTTP /api/*| B3
subgraph S["backend/services"]
S1["workflow_engine.py"]
S2["llm_scheduler.py"]
S3["tool_executor.py"]
S4["mku_agent.py"]
S5["xingyun_mku_agent.py"]
S6["cookie_store.py"]
S7["cookie_manager.py"]
end
B3 -->|POST /chat| S1
B3 -->|POST /generate-material| S3
B3 -->|POST /refresh-cookie| S6
B3 -->|GET /cookie-status| S6
B3 -->|GET /skills| S3
S1 --> S2
S1 --> S3
S2 -->|规则路径| S4
S2 -->|规则路径| S5
S2 -->|通用路径| S3
S4 --> S3
S5 --> S3
S6 --> S7
subgraph K["backend/skills"]
K0["base_skill.py"]
K1["material_generation_skill.py"]
K2["compliance_check_skill.py"]
K3["api_call_skill.py"]
K4["knowledge_retrieval_skill.py"]
K5["jd_* skills (mku/sku/task/cookie status)"]
KX["init.py"]
end
S3 --> KX
KX --> K1
KX --> K2
KX --> K3
KX --> K4
KX --> K5
K1 --> K0
K2 --> K0
K3 --> K0
K4 --> K0
K5 --> K0
subgraph D["backend/data + backend/config"]
D1["config/settings.py (.env)"]
D2["data/mysql_client.py"]
D3["data/redis_client.py"]
D4["data/milvus_client.py"]
end
B2 --> D2
B3 --> D2
S1 --> D3
K4 --> D4
S2 --> D1
S6 --> D1
```
3) `/api/chat` 时序图(编排主链路)
```mermaid
sequenceDiagram
autonumber
participant U as 用户
participant FE as 前端(MainLayout/ChatView)
participant API as FastAPI routes.py
participant WF as workflow_engine.py
participant LLM as llm_scheduler.py
participant EXE as tool_executor.py
participant SK as skills (jd_* / 通用skill)
participant R as redis_client.py
participant DB as mysql_client.py
participant CK as refresh-cookie + cookie_store
U->>FE: 输入指令并点击发送
FE->>API: POST /api/chat {message,user_id}
API->>WF: execute(message)
WF->>R: get(workflow:md5(message))
alt 缓存命中
R-->>WF: cached_result
WF-->>API: final_result
else 缓存未命中
WF->>LLM: parse_and_execute(message)
alt 命中 MKU/行云规则
LLM->>EXE: execute_skill("jd_*", params)
EXE->>SK: skill.execute(...)
SK-->>EXE: result
EXE-->>LLM: result
else Agent可用
LLM->>EXE: (via LangChain tools) execute_skill(...)
EXE->>SK: skill.execute(...)
SK-->>EXE: result
EXE-->>LLM: result
else 简单关键词降级
LLM->>EXE: execute_skill("material/compliance/api/knowledge")
EXE->>SK: skill.execute(...)
SK-->>EXE: result
EXE-->>LLM: result
end
LLM-->>WF: parse_result
WF->>R: set(cache, 3600s)
WF-->>API: final_result
end
API->>DB: 写历史记录(可选)
DB-->>API: 成功/失败(失败忽略)
API-->>FE: {success:true,data:...}
alt 返回 Cookie 失效 error_code
FE->>API: POST /api/refresh-cookie
API->>CK: subprocess 执行 playwright 刷新
CK-->>API: 刷新结果
API-->>FE: refresh success
FE->>API: 自动重试 POST /api/chat
API-->>FE: 新结果
end
FE-->>U: 展示最终响应
```
4) `/api/generate-material` 时序图(直达技能链路)
```mermaid
sequenceDiagram
autonumber
participant U as 用户
participant FE as 前端(MaterialView)
participant API as FastAPI routes.py
participant EXE as tool_executor.py
participant SK as 指定 skill
participant DB as mysql_client.py
participant CK as refresh-cookie + cookie_store
U->>FE: 选择 skill + 填写 params(JSON)
FE->>API: POST /api/generate-material
API->>EXE: execute_skill(skill_name, **params)
EXE->>SK: skill.execute(...)
SK-->>EXE: result
EXE-->>API: {success,data,skill}
API->>DB: 写历史记录(可选)
DB-->>API: 成功/失败(失败忽略)
API-->>FE: {success:true,data:...}
alt data.error_code 为 Cookie 失效
FE->>API: POST /api/refresh-cookie {system}
API->>CK: 调 playwright 刷新 Cookie
CK-->>API: 刷新结果
API-->>FE: refresh success
FE->>API: 自动重试 POST /api/generate-material
API-->>FE: 新结果
end
FE-->>U: 展示生成结果
```