237 lines
6.6 KiB
Markdown
237 lines
6.6 KiB
Markdown
|
|
# BaoDan Workflow 配置指南
|
|||
|
|
|
|||
|
|
> 本文档指导你在 BaoDan 后台创建"产品推荐方案生成"Workflow 应用。
|
|||
|
|
|
|||
|
|
## 前置条件
|
|||
|
|
|
|||
|
|
1. BaoDan 已运行:`http://localhost:3000`
|
|||
|
|
2. 管理员账号已创建(首次访问时设置)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 1:创建 Workflow 应用
|
|||
|
|
|
|||
|
|
1. 打开 `http://localhost:3000`
|
|||
|
|
2. 点击左上角 **"创建应用"** → 选择 **"工作流"**
|
|||
|
|
3. 名称填写:`产品推荐方案生成`
|
|||
|
|
4. 描述填写:`根据客户信息生成三套保险产品推荐方案`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 2:添加节点
|
|||
|
|
|
|||
|
|
在工作流编辑器中,按以下顺序添加 6 个节点:
|
|||
|
|
|
|||
|
|
### 节点 1:参数校验(Code 节点)
|
|||
|
|
|
|||
|
|
- 类型:**代码执行**
|
|||
|
|
- 输入变量:
|
|||
|
|
- `age` (string)
|
|||
|
|
- `gender` (string)
|
|||
|
|
- `occupation` (string)
|
|||
|
|
- `income` (string)
|
|||
|
|
- `budget` (string)
|
|||
|
|
- `insurance_types` (array[string])
|
|||
|
|
- `coverage_amount` (string)
|
|||
|
|
- `coverage_period` (string)
|
|||
|
|
- 代码:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def main(age: str, gender: str, occupation: str, income: str, budget: str,
|
|||
|
|
insurance_types: list, coverage_amount: str, coverage_period: str) -> dict:
|
|||
|
|
errors = []
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
age_int = int(age)
|
|||
|
|
if age_int < 1 or age_int > 150:
|
|||
|
|
errors.append("年龄应在 1-150 之间")
|
|||
|
|
except (ValueError, TypeError):
|
|||
|
|
errors.append("年龄必须是数字")
|
|||
|
|
|
|||
|
|
if gender not in ("male", "female"):
|
|||
|
|
errors.append("性别无效")
|
|||
|
|
|
|||
|
|
if not occupation or not occupation.strip():
|
|||
|
|
errors.append("职业不能为空")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
budget_int = int(budget)
|
|||
|
|
if budget_int < 1:
|
|||
|
|
errors.append("月预算必须大于 0")
|
|||
|
|
except (ValueError, TypeError):
|
|||
|
|
errors.append("月预算必须是数字")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
coverage_int = int(coverage_amount)
|
|||
|
|
if coverage_int < 1:
|
|||
|
|
errors.append("保额必须大于 0")
|
|||
|
|
except (ValueError, TypeError):
|
|||
|
|
errors.append("保额必须是数字")
|
|||
|
|
|
|||
|
|
if not insurance_types:
|
|||
|
|
errors.append("请至少选择一个险种")
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"is_valid": len(errors) == 0,
|
|||
|
|
"error_msg": "; ".join(errors) if errors else "",
|
|||
|
|
"validated_age": age,
|
|||
|
|
"validated_gender": gender,
|
|||
|
|
"validated_occupation": occupation,
|
|||
|
|
"validated_income": income,
|
|||
|
|
"validated_budget": budget,
|
|||
|
|
"validated_types": insurance_types,
|
|||
|
|
"validated_coverage": coverage_amount,
|
|||
|
|
"validated_period": coverage_period,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- 输出变量:`is_valid`, `error_msg`, `validated_*` 系列
|
|||
|
|
|
|||
|
|
### 节点 2:条件分支
|
|||
|
|
|
|||
|
|
- 条件:`node_1.is_valid == true`
|
|||
|
|
- **True 分支** → 节点 3(检索策略)
|
|||
|
|
- **False 分支** → 节点 5(异常处理)
|
|||
|
|
|
|||
|
|
### 节点 3:检索策略生成(Code 节点)
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def main(validated_types: list, validated_age: str, **kwargs) -> dict:
|
|||
|
|
queries = []
|
|||
|
|
for t in validated_types:
|
|||
|
|
queries.append(f"{t} 产品条款 保额 费率 {validated_age}岁")
|
|||
|
|
return {"search_queries": queries}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 节点 4:知识库检索 + LLM 方案生成
|
|||
|
|
|
|||
|
|
**4a. 知识库检索节点**:
|
|||
|
|
- 关联你创建的知识库(各险种文档)
|
|||
|
|
- 检索模式:混合检索
|
|||
|
|
- Top-K = 5
|
|||
|
|
|
|||
|
|
**4b. LLM 节点**:
|
|||
|
|
- 模型:选择你配置的 LLM(如 deepseek-chat)
|
|||
|
|
- Temperature = 0.7
|
|||
|
|
- Prompt 模板:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
你是一位专业的保险规划师。请根据以下客户信息和检索到的产品资料,生成三套保险推荐方案。
|
|||
|
|
|
|||
|
|
## 客户信息
|
|||
|
|
- 年龄:{{node_1.validated_age}}岁
|
|||
|
|
- 性别:{{node_1.validated_gender}}
|
|||
|
|
- 职业:{{node_1.validated_occupation}}
|
|||
|
|
- 年收入:{{node_1.validated_income}}万
|
|||
|
|
- 月预算:{{node_1.validated_budget}}元
|
|||
|
|
- 关注险种:{{node_1.validated_types}}
|
|||
|
|
- 保额目标:{{node_1.validated_coverage}}万
|
|||
|
|
- 保障期限:{{node_1.validated_period}}
|
|||
|
|
|
|||
|
|
## 检索到的产品资料
|
|||
|
|
{{node_4a.text}}
|
|||
|
|
|
|||
|
|
## 输出要求
|
|||
|
|
请生成三套方案(基础型/均衡型/全面型),每套方案包含:
|
|||
|
|
1. 方案名称
|
|||
|
|
2. 年保费合计
|
|||
|
|
3. 产品明细表格(产品名称、保额、年保费、推荐理由)
|
|||
|
|
4. 方案总结
|
|||
|
|
|
|||
|
|
重要规则:
|
|||
|
|
- 保费必须来自检索结果,不得编造
|
|||
|
|
- 总保费不得超过月预算 × 12
|
|||
|
|
- 末尾添加免责声明
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 节点 5:异常处理(Code 节点)
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def main(is_valid: bool, error_msg: str, recommendation: str = "") -> dict:
|
|||
|
|
if not is_valid:
|
|||
|
|
return {"final_output": f"参数校验失败:{error_msg}", "is_success": False}
|
|||
|
|
if not recommendation:
|
|||
|
|
return {"final_output": "未能生成推荐方案,请稍后重试", "is_success": False}
|
|||
|
|
return {"final_output": recommendation, "is_success": True}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 节点 6:格式化输出(Code 节点)
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def main(final_output: str) -> dict:
|
|||
|
|
# 去除多余空行
|
|||
|
|
lines = [l for l in final_output.split("\n") if l.strip()]
|
|||
|
|
return {"result": "\n".join(lines)}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 3:连接节点
|
|||
|
|
|
|||
|
|
按以下顺序连接:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
开始 → 节点1(参数校验) → 节点2(条件分支)
|
|||
|
|
├─ True → 节点3(检索策略) → 节点4a(知识库检索) → 节点4b(LLM生成) → 节点6(格式化) → 结束
|
|||
|
|
└─ False → 节点5(异常处理) → 节点6(格式化) → 结束
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 4:测试
|
|||
|
|
|
|||
|
|
1. 点击右上角 **"运行"** 按钮
|
|||
|
|
2. 输入测试数据:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"age": "35",
|
|||
|
|
"gender": "male",
|
|||
|
|
"occupation": "软件工程师",
|
|||
|
|
"income": "30",
|
|||
|
|
"budget": "2000",
|
|||
|
|
"insurance_types": ["重疾险", "医疗险"],
|
|||
|
|
"coverage_amount": "50",
|
|||
|
|
"coverage_period": "终身"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. 预期:生成三套方案(基础/均衡/全面)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 5:获取 API Key
|
|||
|
|
|
|||
|
|
1. 点击应用右上角 **"发布"**
|
|||
|
|
2. 进入 **"访问 API"** 页面
|
|||
|
|
3. 复制 **API Key**(格式:`app-xxxxxxxxxxxx`)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 步骤 6:配置到项目
|
|||
|
|
|
|||
|
|
运行配置脚本:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd d:/work/code/python/coding/baodanagent
|
|||
|
|
python scripts/setup_baodan_api_keys.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
按提示输入 API Key 即可自动更新 docker-compose 配置。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 常见问题
|
|||
|
|
|
|||
|
|
**Q: 没有知识库怎么办?**
|
|||
|
|
A: 先在 BaoDan 后台 → 知识库 → 创建知识库 → 上传保险产品文档。如果没有文档,可以跳过知识库检索节点,直接让 LLM 生成方案(但方案中的保费数据可能不准确)。
|
|||
|
|
|
|||
|
|
**Q: 没有配置 LLM 模型怎么办?**
|
|||
|
|
A: 在 BaoDan 后台 → 设置 → 模型供应商 → 添加模型(如 OpenAI/DeepSeek)。需要有效的 API Key。
|
|||
|
|
|
|||
|
|
**Q: Workflow 测试通过但 API 调用失败?**
|
|||
|
|
A: 检查 docker-compose.baodan.yml 中的 `BAODAN_WORKFLOW_APP_API_KEY` 是否填入了正确的 API Key,然后重启容器:
|
|||
|
|
```bash
|
|||
|
|
docker compose -f docker-compose.baodan.yml restart baodan-api
|
|||
|
|
```
|