224 lines
6.2 KiB
Markdown
224 lines
6.2 KiB
Markdown
# cabinetTool 返回数据优化方案
|
||
|
||
## 背景
|
||
|
||
`cabinetTool` 查询智能柜详情时,返回的 `cells` 数组可能包含大量格口信息,导致返回给 LLM 的数据量过大,影响响应效率。
|
||
|
||
## 修改目标
|
||
|
||
1. **减少返回数据量**:列表数据(cells)只返回第一条
|
||
2. **增加统计信息**:返回中新增完整的统计信息
|
||
3. **保留完整数据**:完整数据保留在缓存中,供后续使用
|
||
4. **引导使用代码执行**:通过 prompt 说明,引导 Agent 使用 code-executor-tool 提取完整数据
|
||
|
||
## 修改内容
|
||
|
||
### 1. cabinet-tool.ts
|
||
|
||
#### outputSchema 变更
|
||
|
||
新增 `stats` 统计字段:
|
||
|
||
```typescript
|
||
outputSchema: z.object({
|
||
success: z.boolean(),
|
||
message: z.string(),
|
||
data: z.any().optional().describe("柜机信息(cells列表仅返回第一条,完整数据在缓存中)"),
|
||
stats: z.object({
|
||
cellsTotal: z.number().describe("格口总数"),
|
||
cellsFree: z.number().describe("空闲格口数"),
|
||
cellsOccupied: z.number().describe("占用格口数"),
|
||
cellsSmall: z.number().describe("小格数量"),
|
||
cellsMedium: z.number().describe("中格数量"),
|
||
cellsLarge: z.number().describe("大格数量"),
|
||
cellsExtraLarge: z.number().describe("超大格数量"),
|
||
}).optional().describe("统计信息"),
|
||
cacheId: z.string().optional().describe("缓存ID,用于后续引用该查询结果"),
|
||
expiresAt: z.number().optional().describe("缓存过期时间戳"),
|
||
}),
|
||
```
|
||
|
||
#### execute 逻辑变更
|
||
|
||
1. 计算完整统计信息
|
||
2. 将简化数据(仅包含第一条 cell)返回给 LLM
|
||
3. 完整数据(含 stats)存入缓存
|
||
|
||
```typescript
|
||
const cells = response.data?.cells || [];
|
||
|
||
// 计算统计信息
|
||
const stats = {
|
||
cellsTotal: cells.length,
|
||
cellsFree: cells.filter(c => c.usageStatus === 1).length,
|
||
cellsOccupied: cells.filter(c => c.usageStatus === 2).length,
|
||
cellsSmall: cells.filter(c => c.cellType === 1).length,
|
||
cellsMedium: cells.filter(c => c.cellType === 2).length,
|
||
cellsLarge: cells.filter(c => c.cellType === 3).length,
|
||
cellsExtraLarge: cells.filter(c => c.cellType === 4).length,
|
||
};
|
||
|
||
// 简化数据(仅保留第一条cell)
|
||
const firstCell = cells[0] || null;
|
||
const simplifiedData = {
|
||
...response.data,
|
||
cells: firstCell ? [firstCell] : [],
|
||
};
|
||
|
||
// 返回结果
|
||
const result = {
|
||
success: response.code === 0,
|
||
message: response.msg || "查询成功",
|
||
data: simplifiedData,
|
||
stats,
|
||
};
|
||
```
|
||
|
||
### 2. multi-function-agent.ts
|
||
|
||
#### 柜机查询说明更新
|
||
|
||
```
|
||
2. **柜机查询**:使用柜机工具根据柜机ID查询智能柜详细信息。返回数据中格口(cells)列表仅包含第一条,完整数据保留在缓存中。返回结果包含 stats 统计信息(总数、空闲/占用数、各类型数量)。如需获取完整格口列表,请使用代码执行工具通过 cacheId 提取。
|
||
```
|
||
|
||
#### 代码执行示例更新
|
||
|
||
新增 cabinetTool 的缓存使用示例:
|
||
|
||
```markdown
|
||
- 缓存-柜机:code: "return cacheCabinet_0?.data?.cells?.filter(c => c.usageStatus === 1)", cacheIds: ["cacheCabinet_0"] -> 获取所有空闲格口
|
||
- 缓存-柜机:code: "return cacheCabinet_0?.data?.cells?.filter(c => c.cellType === 2)", cacheIds: ["cacheCabinet_0"] -> 获取所有中格
|
||
```
|
||
|
||
## 返回数据结构对比
|
||
|
||
### 修改前
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "查询成功",
|
||
"data": {
|
||
"cabinetId": 1,
|
||
"cabinetName": "柜机A",
|
||
"cells": [
|
||
{ "cellId": 1, "cellNo": 1, ... },
|
||
{ "cellId": 2, "cellNo": 2, ... },
|
||
{ "cellId": 3, "cellNo": 3, ... }
|
||
// ... 更多格口
|
||
]
|
||
},
|
||
"cacheId": "cacheCabinet_1",
|
||
"expiresAt": 1700000000000
|
||
}
|
||
```
|
||
|
||
### 修改后
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "查询成功",
|
||
"data": {
|
||
"cabinetId": 1,
|
||
"cabinetName": "柜机A",
|
||
"cells": [
|
||
{ "cellId": 1, "cellNo": 1, ... }
|
||
]
|
||
},
|
||
"stats": {
|
||
"cellsTotal": 50,
|
||
"cellsFree": 30,
|
||
"cellsOccupied": 20,
|
||
"cellsSmall": 10,
|
||
"cellsMedium": 20,
|
||
"cellsLarge": 15,
|
||
"cellsExtraLarge": 5
|
||
},
|
||
"cacheId": "cacheCabinet_1",
|
||
"expiresAt": 1700000000000
|
||
}
|
||
```
|
||
|
||
### 缓存数据(完整)
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "查询成功",
|
||
"data": {
|
||
"cabinetId": 1,
|
||
"cabinetName": "柜机A",
|
||
"cells": [
|
||
{ "cellId": 1, "cellNo": 1, ... },
|
||
{ "cellId": 2, "cellNo": 2, ... },
|
||
{ "cellId": 3, "cellNo": 3, ... }
|
||
// ... 所有格口
|
||
]
|
||
},
|
||
"stats": {
|
||
"cellsTotal": 50,
|
||
"cellsFree": 30,
|
||
"cellsOccupied": 20,
|
||
"cellsSmall": 10,
|
||
"cellsMedium": 20,
|
||
"cellsLarge": 15,
|
||
"cellsExtraLarge": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
### 场景1:查询柜机概况
|
||
|
||
直接使用 cabinetTool,获取统计信息:
|
||
|
||
```
|
||
用户:查询柜机1的概况
|
||
Agent -> cabinetTool(cabinetId: 1) -> 返回 stats 信息
|
||
```
|
||
|
||
### 场景2:获取所有空闲格口
|
||
|
||
使用代码执行工具通过 cacheId 提取:
|
||
|
||
```
|
||
用户:柜机1有哪些空闲格口?
|
||
Agent -> cabinetTool(cabinetId: 1) -> codeExecutorTool(
|
||
code: "return cacheCabinet_0?.data?.cells?.filter(c => c.usageStatus === 1)",
|
||
cacheIds: ["cacheCabinet_0"]
|
||
) -> 返回空闲格口列表
|
||
```
|
||
|
||
### 场景3:筛选特定类型格口
|
||
|
||
结合 context 参数筛选:
|
||
|
||
```
|
||
用户:柜机1有哪些大格可以存放商品?
|
||
Agent -> cabinetTool(cabinetId: 1) -> codeExecutorTool(
|
||
code: "return cacheCabinet_0?.data?.cells?.filter(c => c.cellType === 3 && c.usageStatus === 1)",
|
||
cacheIds: ["cacheCabinet_0"]
|
||
) -> 返回空闲大格列表
|
||
```
|
||
|
||
## 修改文件清单
|
||
|
||
| 文件 | 修改类型 | 说明 |
|
||
|------|---------|------|
|
||
| `src/mastra/tools/cabinet-tool.ts` | 修改 | outputSchema 新增 stats 字段,execute 逻辑简化返回数据 |
|
||
| `src/mastra/agents/multi-function-agent.ts` | 修改 | 更新 instructions,说明返回数据和缓存使用方式 |
|
||
| `doc/cabinet-tool-optimization.md` | 新建 | 文档总结修改方案 |
|
||
|
||
## 验证步骤
|
||
|
||
1. **构建项目**:运行 `pnpm build` 确保无编译错误
|
||
2. **启动服务**:运行 `pnpm dev` 启动开发服务器
|
||
3. **测试 API**:调用 cabinetTool,检查返回数据是否符合预期
|
||
4. **测试场景**:
|
||
- 查询单个柜机,检查返回数据是否只包含第一条 cell
|
||
- 使用 code-executor-tool 提取所有空闲格口
|
||
- 使用 code-executor-tool 统计格口类型分布
|