Files

122 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🚀 Enterprise AI Agent Gateway (企业级 AI 智能体网关) - 核心架构与开发设计书
## 1. 架构定位与核心设计理念
本系统是一个定位于大模型(LLM/AI Agent)与企业老旧业务系统(Legacy Systems)之间的**安全中间件与协议转换枢纽**。
* **零侵入架构**:老系统无需修改任何代码,通过本网关即可将现有 API 暴露为标准的大模型 Tool Schema。
* **控制面与数据面分离**:
* **控制面 (Control Plane)**:前端可视化配置,业务人员通过“表单填报”或“AI 辅助生成”完成 API 注册与清洗规则设定。
* **数据面 (Data Plane)**:纯粹的 Java 高并发执行引擎,负责鉴权、状态挂起(人工审批)、代理调用与底层 GraalVM 极速数据洗涤。
## 2. 技术栈选型
* **数据面网关核心**:Spring Boot 3.x (WebFlux/纯 WebMVC) + JDK 17/21。
* **清洗执行引擎**:GraalVM Polyglot (内嵌高安全级别的 JavaScript 运行时沙箱)。
* **缓存与风控**:Redis (分布式限流、状态机挂起) + Caffeine (本地极速配置缓存)。
* **控制面后端**:Spring Boot / FastAPI (提供标准的 CRUD 接口)。
* **前端管理台**:Vue 3 + Element Plus / Ant Design Vue + Monaco Editor。
* **数据存储**:MySQL 8.0。
---
## 3. 核心数据库实体模型 (MySQL 8.0 DDL 需求)
> **To Antigravity**: 请基于以下实体关系,优先生成 DDL 建表语句以及对应的底层 CRUD 代码(Entity/Mapper/Service)。
### 3.1 `ai_tenant` (租户/AI 助手接入表)
* `id`: 主键
* `tenant_name`: 租户/机器人名称(例:“财务客服 Agent”)
* `app_key`: 网关调用的唯一凭证 (唯一索引)
* `app_secret`: 签名与加解密密钥
* `rate_limit_qps`: 该租户的全局 QPS 限制阈值
* `status`: 状态 (启用/禁用)
### 3.2 `ai_tool_registry` (API 工具注册表)
* `id`: 主键
* `tool_name`: 工具标识(英文下划线,符合 LLM 命名规范)
* `description`: 喂给大模型的详细描述(决定 LLM 是否调用该工具的核心依据)
* `action_type`: `READ` (默认放行) / `WRITE` (高危,强制触发人工审批)
* `target_url`: 底层老系统的真实内网 URL
* `http_method`: GET / POST
* `request_schema`: 请求参数的标准 JSON Schema (用于 LLM 识别)
### 3.3 `ai_tenant_tool_rel` (权限控制映射表)
* `tenant_id`: 关联 `ai_tenant.id`
* `tool_id`: 关联 `ai_tool_registry.id`
### 3.4 `ai_wash_script` (GraalVM 数据清洗脚本表)
* `tool_id`: 唯一关联 `ai_tool_registry.id`
* `js_script`: 具体的 JavaScript 源码文本(由控制面生成,供数据面 GraalVM 执行)
* `version`: 版本号,用于并发控制和缓存刷新
### 3.5 `ai_audit_log` (全链路安全审计日志表)
* `trace_id`: 全局请求流水号 (UUID)
* `tenant_id`: 关联的租户 ID
* `tool_name`: 命中的工具名称
* `raw_request`: AI 发起的原始 JSON 参数
* `raw_response`: 老系统返回的巨型原始 JSON (MediumText)
* `washed_response`: 经过 GraalVM JS 脚本洗涤后的纯净 JSON
* `cost_time_ms`: 总耗时 (毫秒)
---
## 4. 控制面前端 (Vue 3) 交互设计规范
前端的核心目标是**隐藏 JavaScript 的编写复杂度**。对于清洗规则 (`ai_wash_script`) 的配置页面,需实现以下三层交互降级方案:
1. **AI Copilot 生成(主推)**:页面提供左侧输入“原始 JSON 样例”,上方输入“自然语言提取需求”,点击按钮后,后台调用大模型生成 JS 代码并填充。
2. **可视化勾选表单(中阶)**:提供“保留字段白名单”、“移除 Null 值”、“拍平数组”等勾选项,前端根据勾选自动拼接为 JS 字符串。
3. **Monaco Editor 兜底(高阶)**:提供类似 VS Code 的代码编辑框,允许懂代码的开发人员直接修正在线生成的 JavaScript 规则。
---
## 5. 数据面网关 Pipeline (责任链/Filter Chain 设计)
> **To Antigravity**: 在生成网关核心转发逻辑时,请严格按照以下 Filter 顺序构建职责链模式。
1. **Config Watcher (配置加载)**:定时从 MySQL 拉取 `ai_tool_registry`、权限与 `js_script`,加载至 Caffeine 内存。
2. **Auth & Rate Limiting (鉴权限流)**:校验 `app_key`,拦截非法调用;利用 Redis 执行令牌桶限流。
3. **Identity OBO (权限穿透)**:若包含终端用户 Token,将该身份附加至 Downstream Header 中。
4. **HITL Suspender (审批挂起)**:若 `action_type == 'WRITE'`,拦截当前线程,向外部(如企微/钉钉)发送包含审批链接的 Webhook,当前请求挂起等待回调。
5. **Proxy Execution (代理转发)**:组装参数,向 `target_url` 发起真实的 HTTP 内部请求。
6. **GraalVM Washing (洗涤瘦身)**:拿到原始大 JSON,在限制了内存与执行时间(如 max 100ms)的 GraalVM 沙箱中执行对应的 `js_script`,返回瘦身结果。
7. **Async Audit (异步审计)**:无论成功失败,将完整上下文抛入线程池,落库至 `ai_audit_log`。
---
## 6. 核心资产:AI 辅助生成清洗脚本的 System Prompt
> 针对控制面的“AI 自动生成 JS 规则”功能,后端需要内置以下 System Prompt。
```text
# Role
你是一个资深的 JavaScript 数据处理专家与大模型工程架构师。
# Objective
你的任务是根据用户提供的【原始庞大 JSON 样例】和【自然语言提取要求】,编写一段精简、安全、高效的 JavaScript 代码,用于在 GraalVM 环境下对 JSON 进行瘦身清洗。这段清洗后的数据将被直接喂给大模型(LLM)作为上下文。
# Constraints & Rules
1. 你的输出必须且只能包含一个名为 `wash` 的 JavaScript 函数。
2. 该函数的入参必须是 `rawJsonString` (字符串类型)。
3. 该函数的返回值必须是清洗并序列化后的 JSON 字符串,以确保后续直接使用。
4. 代码必须健壮,需处理常见的空指针(undefined/null)和数组越界异常。
5. 必须剔除所有无业务价值的字段(如 HTML 标签、内部 traceId、全 null 字段等),最大限度节省 LLM 的 Token。
6. 不要使用任何外部依赖或 npm 包,只能使用 ES6+ 标准原生语法。
# Output Format Example
```javascript
function wash(rawJsonString) {
try {
const data = JSON.parse(rawJsonString);
if (!data || !data.list) return "[]";
const result = data.list.map(item => ({
eventName: item.event_name || '未知',
date: item.timestamp ? new Date(item.timestamp).toISOString().split('T')[0] : '',
coreProfit: item.financial_data?.net_profit ?? 0
}));
return JSON.stringify(result);
} catch (e) {
return JSON.stringify({ error: "数据清洗失败" });
}
}
```