baodan/docs/保险智能客服系统_API接口文档.md

1301 lines
33 KiB
Markdown
Raw 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.

# 保险智能客服系统 — API 接口文档
> **版本**V1.1(与需求文档 V1.0 对齐)
> **基础路径**`/api`
> **认证方式**JWT Bearer TokenHeader: `Authorization: Bearer <token>`
> **内容类型**`application/json`(除文件上传接口外)
> **接口总数**45 个(含企微/健康检查)
---
## 一、全局约定
### 1.1 统一响应格式
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
- `code = 0`:成功
- `code != 0`:失败,`message` 为错误描述,`data` 为 null 或错误详情
### 1.2 错误码表
| 错误码 | 说明 | 处理建议 |
|:---:|------|---------|
| 0 | 成功 | - |
| 1001 | 参数错误 | 检查请求参数 |
| 1002 | 未授权 | 重新登录 |
| 1003 | Token 已过期 | 调用 refresh-token |
| 1004 | 权限不足 | 联系管理员 |
| 1005 | 资源不存在 | 检查资源 ID |
| 2001 | BaoDan API 调用失败 | 检查 BaoDan 服务 |
| 2002 | BaoDan API 超时 | 重试 |
| 2003 | BaoDan Workflow 失败 | 检查 Workflow 配置 |
| 3001 | 企微 API 调用失败 | 检查企微配置 |
| 4001 | 文件上传失败 | 检查文件格式/大小 |
| 9999 | 服务器内部错误 | 检查日志 |
### 1.3 分页参数
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| page | int | 1 | 页码 |
| page_size | int | 20 | 每页条数,最大 100 |
### 1.4 认证方式
所有标注"需要认证"的接口,请求 Header 必须包含:
```
Authorization: Bearer <JWT_TOKEN>
```
JWT Token 有效期 2 小时7200 秒),过期后调用 `/api/auth/refresh-token` 刷新。
### 1.5 实现方式标注
| 标注 | 含义 |
|------|------|
| 自研(调 BaoDan | 自研后端接口,内部调 BaoDan API |
| 自研 | 完全自研 |
| BaoDan 原生 | 直接使用 BaoDan不需要自研后端 |
| BaoDan + 增强 | BaoDan 有基础,需要少量增强代码 |
---
## 二、系统接口
### 2.1 健康检查
| 项 | 值 |
|----|---|
| URL | `GET /api/health` |
| 认证 | 不需要 |
| 实现 | 自研 |
**响应**
```json
{ "status": "ok" }
```
### 2.2 企微机器人回调URL 验证)
| 项 | 值 |
|----|---|
| URL | `GET /api/wecom/callback` |
| 认证 | 不需要(企微签名校验) |
| 实现 | 自研 + 企微 API |
**参数**`msg_signature`、`timestamp`、`nonce`、`echostr`
**响应**:解密后的 echostr纯文本非 JSON
**处理逻辑**
1. 将 Token、timestamp、nonce、echostr 按字典序排列拼接
2. SHA1 哈希,与 msg_signature 比对
3. 验证通过则返回解密后的 echostr
### 2.3 企微机器人消息接收
| 项 | 值 |
|----|---|
| URL | `POST /api/wecom/callback` |
| 认证 | 不需要(企微签名校验) |
| 实现 | 自研 + 企微 API |
**请求体**:企微加密的 XML 消息体
**响应**`success`(纯文本,必须在 5 秒内返回)
**处理逻辑**
1. 验证签名 + 解密 XML
2. 判断 MsgType文本消息继续处理非文本回复"暂不支持"
3. 群聊消息去掉"@机器人"前缀
4. **立即返回 `success`**
5. 异步处理:调 BaoDan Chat API → 通过企微 API 回复用户
### 2.4 企微 OAuth 登录入口
| 项 | 值 |
|----|---|
| URL | `GET /api/wecom/oauth` |
| 认证 | 不需要 |
| 实现 | 自研 |
**响应**302 重定向到企微授权页面
### 2.5 企微 OAuth 回调
| 项 | 值 |
|----|---|
| URL | `GET /api/wecom/oauth/callback` |
| 认证 | 不需要 |
| 实现 | 自研 |
**参数**`code`(企微授权码)、`state`
**处理逻辑**
1. 用 code 换取企微 access_token
2. 获取用户信息userid、name、department
3. 查找/创建 wecom_user_mapping 记录
4. 生成 JWT Token
5. 302 重定向到前端首页
---
## 三、认证鉴权A1
### A1.1.1 企微登录
| 项 | 值 |
|----|---|
| URL | `POST /api/auth/wework-login` |
| 认证 | 不需要 |
| 实现 | 自研(调 BaoDan |
**请求**
```json
{
"code": "企微授权回调code",
"state": "随机状态值"
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| code | string | 是 | 1-512 字符 | "授权码无效" |
| state | string | 否 | 0-256 字符 | - |
**响应**
```json
{
"code": 0,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 7200,
"user": {
"id": "user-001",
"username": "张三",
"wecom_userid": "zhangsan",
"role": "sales",
"department": "上海团队"
}
}
}
```
### A1.1.2 账密登录
| 项 | 值 |
|----|---|
| URL | `POST /api/auth/password-login` |
| 认证 | 不需要 |
| 实现 | 自研(调 BaoDan |
**请求**
```json
{
"username": "admin",
"password": "hashed_password"
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| username | string | 是 | 1-64 字符,非空 | "请输入用户名" |
| password | string | 是 | 1-128 字符,非空 | "请输入密码" |
**响应**
```json
{
"code": 0,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 7200
}
}
```
**失败响应**
```json
{ "code": 1002, "message": "用户名或密码错误" }
```
### A1.1.3 刷新 Token
| 项 | 值 |
|----|---|
| URL | `POST /api/auth/refresh-token` |
| 认证 | 需要(旧 Token |
| 实现 | 自研(调 BaoDan |
**响应**
```json
{
"code": 0,
"data": { "token": "eyJhbGci...", "expires_in": 7200 }
}
```
### A1.1.4 退出登录
| 项 | 值 |
|----|---|
| URL | `POST /api/auth/logout` |
| 认证 | 需要 |
| 实现 | 自研 |
**处理**:将当前 Token 加入黑名单Redis后续请求使用该 Token 时返回 1002。
**响应**
```json
{ "code": 0, "message": "success" }
```
---
## 四、智能问答A2
### A2.1.1 发送消息SSE 流式)
| 项 | 值 |
|----|---|
| URL | `POST /api/chat/message` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**请求**
```json
{
"session_id": "sess-001",
"message": "重疾险的等待期是多少天?",
"filters": { "险种": "重疾险", "保司": null }
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 |
|------|------|:---:|------|------|---------|
| message | string | 是 | 1-10000 字符 | - | "请输入问题内容" |
| session_id | string | 否 | UUID 格式,空串=新对话 | - | "会话ID格式无效" |
| filters | object | 否 | - | - | - |
| filters.险种 | string | 否 | 0-32 字符 | 重疾险/寿险/医疗险/意外险/车险/年金险/储蓄险 | "不支持的险种" |
| filters.保司 | string | 否 | 0-64 字符 | - | - |
**响应**SSE 流式,`Content-Type: text/event-stream`
```
data: {"type":"source","data":{"doc_name":"XX重疾险条款.md","chunk":"等待期为合同生效之日起90天..."}}
data: {"type":"delta","data":"根据"}
data: {"type":"delta","data":"XX重疾险条款规定等待期为90天。"}
data: {"type":"done","data":{"message_id":"msg-001","conversation_id":"conv-001"}}
```
**SSE 事件类型**
| type | 说明 | data 结构 |
|------|------|----------|
| source | 来源引用 | `{doc_name, chunk, score}` |
| delta | 文本增量 | `{data: "文本片段"}` |
| done | 回答完成 | `{message_id, conversation_id}` |
| error | 错误 | `{message}` |
### A2.1.2 获取会话列表
| 项 | 值 |
|----|---|
| URL | `GET /api/chat/sessions` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**查询参数**`page`、`page_size`
**响应**
```json
{
"code": 0,
"data": {
"total": 35,
"items": [
{
"id": "sess-001",
"title": "重疾险等待期问题",
"created_at": "2026-05-31T10:00:00Z",
"updated_at": "2026-05-31T10:05:00Z",
"message_count": 6
}
]
}
}
```
### A2.1.3 创建会话
| 项 | 值 |
|----|---|
| URL | `POST /api/chat/sessions` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**响应**
```json
{ "code": 0, "data": { "session_id": "sess-002" } }
```
### A2.1.4 删除会话
| 项 | 值 |
|----|---|
| URL | `DELETE /api/chat/sessions/{id}` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**路径参数**`id`UUID 格式,错误提示:"会话ID格式无效"
**响应**
```json
{ "code": 0, "message": "success" }
```
### A2.1.5 获取消息记录
| 项 | 值 |
|----|---|
| URL | `GET /api/chat/sessions/{id}/messages` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**响应**
```json
{
"code": 0,
"data": {
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "重疾险的等待期是多少天?",
"created_at": "2026-05-31T10:00:00Z"
},
{
"id": "msg-002",
"role": "assistant",
"content": "根据 XX 重疾险条款规定等待期为合同生效之日起90天。",
"sources": [
{"doc_name": "XX重疾险条款.md", "chunk": "等待期为..."}
],
"created_at": "2026-05-31T10:00:05Z"
}
]
}
}
```
### A2.1.6 提交反馈
| 项 | 值 |
|----|---|
| URL | `POST /api/chat/messages/{id}/feedback` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**请求(有用)**
```json
{ "rating": "helpful", "comment": null }
```
**请求(纠错)**
```json
{ "rating": "not_helpful", "comment": "等待期应该是180天而不是90天" }
```
**字段约束**
| 字段 | 类型 | 必填 | 枚举 | 错误提示 |
|------|------|:---:|------|---------|
| rating | string | 是 | helpful / not_helpful | "评分值无效" |
| comment | string | 否 | 0-2000 字符 | - |
### A2.2.1 向量检索
| 项 | 值 |
|----|---|
| URL | `POST /api/retrieval/search` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**请求**
```json
{
"query": "重疾险等待期",
"filters": { "险种": "重疾险", "保司": null },
"top_k": 5
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 默认值 | 错误提示 |
|------|------|:---:|------|--------|---------|
| query | string | 是 | 1-1000 字符 | - | "请输入搜索内容" |
| filters.险种 | string | 否 | 枚举值 | null | "不支持的险种" |
| top_k | int | 否 | 1-20 | 5 | "top_k 应在 1-20 之间" |
**响应**
```json
{
"code": 0,
"data": {
"results": [
{
"doc_name": "XX重疾险条款.md",
"chunk": "等待期为合同生效之日起90天...",
"score": 0.92,
"metadata": { "险种": "重疾险", "保司": "XX人寿" }
}
]
}
}
```
### A2.2.2 推荐追问
| 项 | 值 |
|----|---|
| URL | `POST /api/chat/suggest` |
| 认证 | 需要 |
| 实现 | 自研 |
**请求**
```json
{ "message": "根据 XX 重疾险条款规定等待期为90天。" }
```
**响应**
```json
{
"code": 0,
"data": {
"suggestions": [
"重疾险的免赔额是多少?",
"哪些情况不在理赔范围内?",
"等待期内出险怎么处理?"
]
}
}
```
---
## 五、方案生成A3
### A3.1.1 生成推荐方案
| 项 | 值 |
|----|---|
| URL | `POST /api/recommend/generate` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan Workflow |
**请求**
```json
{
"customer": {
"name": "李四",
"age": 35,
"gender": "male",
"health_status": "健康",
"occupation": "软件工程师",
"annual_income": 300000,
"monthly_budget": 2000
},
"insurance_types": ["重疾险", "医疗险", "意外险"],
"coverage_amount": 500000,
"coverage_period": "终身",
"existing_policies": []
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 |
|------|------|:---:|------|------|---------|
| customer.age | int | 是 | 0-150 | - | "年龄应在 0-150 之间" |
| customer.gender | string | 是 | - | male/female | "性别值无效" |
| customer.health_status | string | 是 | 1-32 字符 | 健康/有既往病史/慢性病/重大疾病史 | "健康状况值无效" |
| customer.occupation | string | 是 | 1-50 字符 | - | "请输入职业" |
| customer.annual_income | int | 是 | >=0 | - | "年收入不能为负数" |
| customer.monthly_budget | int | 是 | >=1 | - | "月预算必须大于 0" |
| insurance_types | string[] | 是 | 1-10 项 | 寿险/重疾险/医疗险/意外险/年金险/储蓄险 | "请至少选择一个险种" |
| coverage_amount | int | 是 | >=1 | - | "保额必须大于 0" |
| coverage_period | string | 是 | - | 定期10年/20年/30年/保至60岁/70岁/80岁/终身 | "请选择保障期限" |
| existing_policies | object[] | 否 | 0-20 项 | - | - |
**响应**
```json
{ "code": 0, "data": { "task_id": "task-001", "status": "processing" } }
```
### A3.1.2 轮询任务状态
| 项 | 值 |
|----|---|
| URL | `GET /api/recommend/generate/{task_id}` |
| 认证 | 需要 |
| 实现 | 自研 |
**字段约束**`task_id`UUID 格式,错误提示:"任务ID格式无效"
**响应(生成中)**
```json
{ "code": 0, "data": { "task_id": "task-001", "status": "processing" } }
```
**响应(完成)**
```json
{
"code": 0,
"data": {
"task_id": "task-001",
"status": "done",
"proposal": {
"id": "prop-001",
"plans": [
{
"name": "基础方案",
"total_premium": 4800,
"items": [
{
"product_name": "XX重疾险",
"coverage": 300000,
"premium": 2400,
"reason": "35岁男性投保性价比高覆盖120种重疾"
}
],
"summary": "基础保障方案,覆盖重疾、医疗、意外三大类..."
}
]
}
}
}
```
**响应(失败)**
```json
{ "code": 0, "data": { "task_id": "task-001", "status": "failed", "error_message": "生成超时" } }
```
### A3.1.3 方案导出
| 项 | 值 |
|----|---|
| URL | `POST /api/recommend/{id}/export` |
| 认证 | 需要 |
| 实现 | 自研 |
**请求**`{ "format": "pdf" }`
**字段约束**
| 字段 | 类型 | 必填 | 枚举 | 错误提示 |
|------|------|:---:|------|---------|
| format | string | 是 | pdf/pptx/docx | "不支持的导出格式" |
**响应**
```json
{
"code": 0,
"data": {
"download_url": "https://your-domain.com/api/recommend/{id}/download?token=xxx",
"expire_at": "2026-06-03T10:00:00Z"
}
}
```
### A3.1.4 生成分享链接
| 项 | 值 |
|----|---|
| URL | `POST /api/recommend/{id}/share` |
| 认证 | 需要 |
| 实现 | 自研 |
**请求**`{ "expire_hours": 72 }`
**字段约束**`expire_hours`int1-720错误提示"有效期应在 1-720 小时之间"
**响应**
```json
{
"code": 0,
"data": {
"share_url": "https://your-domain.com/shared/prop-001?token=xxx",
"expire_at": "2026-06-03T10:00:00Z"
}
}
```
---
## 六、知识库A4
### A4.1.1 上传文档
| 项 | 值 |
|----|---|
| URL | `POST /api/kb/documents/upload` |
| Content-Type | multipart/form-data |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**表单字段**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| files | file[] | 是 | 1-50 个文件,每个 <50MB格式 md/word/txt | "仅支持 MD/Word/TXT 格式" |
| 险种 | string | | 1-32 字符 | "请选择险种" |
| 保司 | string | | 1-64 字符 | "请填写保司名称" |
**响应**
```json
{
"code": 0,
"data": {
"upload_id": "upload-001",
"documents": [
{ "doc_id": "doc-001", "filename": "file1.md", "status": "processing" }
]
}
}
```
### A4.1.2 文档列表
| | |
|----|---|
| URL | `GET /api/kb/documents` |
| 认证 | 需要 |
| 实现 | 自研 BaoDan |
**查询参数**
| 参数 | 类型 | 必填 | 约束 | 枚举值 |
|------|------|:---:|------|--------|
| page | int | | >=1默认 1 | - |
| page_size | int | 否 | 1-100默认 20 | - |
| 险种 | string | 否 | 0-32 | - |
| 保司 | string | 否 | 0-64 | - |
| status | string | 否 | - | pending/processing/completed/failed |
| keyword | string | 否 | 0-100 | - |
**响应**
```json
{
"code": 0,
"data": {
"total": 150,
"items": [
{
"doc_id": "doc-001",
"filename": "XX重疾险条款.md",
"编号": "CJ-XX-001",
"险种": "重疾险",
"保司": "XX人寿",
"tags": ["产品条款", "等待期"],
"status": "completed",
"uploaded_at": "2026-05-15T10:00:00Z",
"processed_at": "2026-05-15T10:05:00Z"
}
]
}
}
```
### A4.1.3 文档处理状态
| 项 | 值 |
|----|---|
| URL | `GET /api/kb/documents/{id}/status` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**响应**
```json
{
"code": 0,
"data": {
"doc_id": "doc-001",
"filename": "XX重疾险条款.md",
"pipeline": [
{ "stage": "upload", "status": "completed", "time": "2026-05-15T10:00:01Z" },
{ "stage": "format_convert", "status": "completed", "time": "2026-05-15T10:00:02Z" },
{ "stage": "chunking", "status": "completed", "time": "2026-05-15T10:00:03Z", "chunk_count": 45 },
{ "stage": "embedding", "status": "completed", "time": "2026-05-15T10:05:00Z" }
]
}
}
```
### A4.1.4 重试失败文档
| 项 | 值 |
|----|---|
| URL | `POST /api/kb/documents/{id}/retry` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
### A4.1.5 更新文档元数据
| 项 | 值 |
|----|---|
| URL | `PATCH /api/kb/documents/{id}` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
**请求**`{ "编号": "CJ-XX-002", "tags": ["产品条款", "核保"] }`
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| 编号 | string | 否 | 0-32 字符 | "编号格式无效" |
| tags | string[] | 否 | 0-20 项,每项 1-32 字符 | - |
### A4.1.6 删除文档
| 项 | 值 |
|----|---|
| URL | `DELETE /api/kb/documents/{id}` |
| 认证 | 需要 |
| 实现 | 自研(调 BaoDan |
### A4.2.1 数据源列表
| 项 | 值 |
|----|---|
| URL | `GET /api/kb/datasources` |
| 认证 | 需要 |
| 实现 | 自研 |
**响应**
```json
{
"code": 0,
"data": [
{
"id": "ds-001",
"name": "XX人寿产品接口",
"api_url": "https://api.xxlife.com/products",
"sync_frequency": "0 2 * * *",
"last_sync": "2026-05-31T02:00:00Z",
"last_sync_status": "success",
"last_sync_count": 156
}
]
}
```
### A4.2.2 新建数据源
| 项 | 值 |
|----|---|
| URL | `POST /api/kb/datasources` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
**请求**
```json
{
"name": "XX人寿产品接口",
"api_url": "https://api.xxlife.com/products",
"api_key": "encrypted_key_here",
"sync_frequency": "0 2 * * *"
}
```
### A4.2.3 手动同步
| 项 | 值 |
|----|---|
| URL | `POST /api/kb/datasources/{id}/sync` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
### A4.2.4 同步日志
| 项 | 值 |
|----|---|
| URL | `GET /api/kb/datasources/{id}/logs` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
---
## 七、用户权限A5
### A5.1.1 用户管理
| 项 | 值 |
|----|---|
| URL | `GET/POST/PUT/DELETE /api/admin/users` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**GET 列表请求**`GET /api/admin/users?page=1&page_size=20&role=sales&department=上海团队`
**GET 列表响应**
```json
{
"code": 0,
"data": {
"total": 50,
"items": [
{
"id": "user-001",
"username": "张三",
"wecom_userid": "zhangsan",
"role": "sales",
"department": "上海团队",
"status": "active",
"created_at": "2026-05-01T10:00:00Z",
"last_active_at": "2026-05-31T09:30:00Z"
}
]
}
}
```
**POST 新增请求**
```json
{
"username": "李四",
"wecom_userid": "lisi",
"role": "sales",
"department": "上海团队"
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 |
|------|------|:---:|------|------|---------|
| username | string | 是 | 1-64不可重复 | - | "用户名已存在" |
| role | string | 是 | - | super_admin/admin/manager/sales | "角色值无效" |
**PUT 编辑**`PUT /api/admin/users/{id}`
**DELETE 停用**`DELETE /api/admin/users/{id}`(停用时吊销所有 Token
### A5.1.2 批量导入用户
| 项 | 值 |
|----|---|
| URL | `POST /api/admin/users/batch-import` |
| Content-Type | multipart/form-data |
| 认证 | 需要(超级管理员) |
| 实现 | 自研 |
### A5.1.3 角色管理
| 项 | 值 |
|----|---|
| URL | `GET/POST/PUT/DELETE /api/admin/roles` |
| 认证 | 需要(超级管理员) |
| 实现 | 自研 |
**GET 响应**
```json
{
"code": 0,
"data": [
{ "id": "role-001", "name": "超级管理员", "permissions": ["*"], "builtin": true },
{ "id": "role-002", "name": "管理员", "permissions": ["kb_manage","log_view","user_manage","config_manage"], "builtin": true },
{ "id": "role-003", "name": "销售主管", "permissions": ["chat","proposal","kb_view","team_stats"], "builtin": true },
{ "id": "role-004", "name": "销售人员", "permissions": ["chat","proposal"], "builtin": true },
{ "id": "role-005", "name": "客户", "permissions": ["chat"], "builtin": true }
]
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| name | string | 是 | 1-32不可重复 | "角色名已存在" |
| permissions | string[] | 是 | 1-50 项 | "权限标识无效" |
---
## 八、系统配置A6
### A6.1.1 LLM 配置
| 项 | 值 |
|----|---|
| URL | `GET/POST/PUT /api/admin/llm-configs` |
| 认证 | 需要(超级管理员) |
| 实现 | 自研(调 BaoDan |
**POST 请求**
```json
{
"provider": "deepseek",
"model": "deepseek-chat",
"api_key": "sk-xxxxxxxxxxxx",
"base_url": "https://api.deepseek.com/v1",
"is_default": true,
"params": { "temperature": 0.7, "max_tokens": 4096, "top_p": 0.9 }
}
```
**字段约束**
| 字段 | 类型 | 必填 | 枚举 | 错误提示 |
|------|------|:---:|------|---------|
| provider | string | 是 | deepseek/openai/zhipu/qwen | "不支持的供应商" |
| model | string | 是 | 1-64 字符 | "请输入模型名称" |
| api_key | string | 是 | 1-512 字符 | "请输入 API Key" |
**POST 响应**
```json
{
"code": 0,
"data": {
"id": "llm-001",
"provider": "deepseek",
"model": "deepseek-chat",
"api_key_masked": "sk-xxxx****xxxx",
"is_default": true,
"status": "active"
}
}
```
### A6.1.2 连通性测试
| 项 | 值 |
|----|---|
| URL | `POST /api/admin/llm-configs/{id}/ping` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**响应**
```json
{ "code": 0, "data": { "reachable": true, "latency_ms": 320, "model": "deepseek-chat" } }
```
### A6.1.3 Prompt 管理
| 项 | 值 |
|----|---|
| URL | `GET/POST/PUT /api/admin/prompts` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**POST 请求**
```json
{
"name": "保险顾问系统提示词",
"type": "system",
"content": "你是一名专业的保险顾问助手...",
"variables": ["险种", "保司"]
}
```
**字段约束**
| 字段 | 类型 | 必填 | 约束 | 错误提示 |
|------|------|:---:|------|---------|
| content | string | 是 | 1-100000 字符 | "Prompt 内容不能为空" |
**POST 响应**(自动生成版本快照):
```json
{
"code": 0,
"data": {
"id": "prompt-001",
"name": "保险顾问系统提示词",
"version": 3,
"versions": [
{"version": 1, "created_at": "2026-05-01T10:00:00Z"},
{"version": 2, "created_at": "2026-05-15T10:00:00Z"},
{"version": 3, "created_at": "2026-05-31T10:00:00Z"}
]
}
}
```
### A6.1.4 Prompt 测试
| 项 | 值 |
|----|---|
| URL | `POST /api/admin/prompts/test` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**请求**`{ "prompt_id": "prompt-001", "test_query": "重疾险等待期多少天?" }`
**响应**
```json
{
"code": 0,
"data": {
"response": "根据条款规定重疾险等待期为90天...",
"latency_ms": 1200,
"token_usage": { "prompt_tokens": 520, "completion_tokens": 180 }
}
}
```
---
## 九、留痕日志A7
### A7.1.1 问答记录查询
| 项 | 值 |
|----|---|
| URL | `GET /api/admin/logs/chat` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**查询参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|:---:|------|
| page | int | 否 | 页码,默认 1 |
| page_size | int | 否 | 每页条数,默认 50 |
| user_id | string | 否 | 按用户筛选 |
| start_date | string | 否 | 开始日期 YYYY-MM-DD |
| end_date | string | 否 | 结束日期 YYYY-MM-DD |
| keyword | string | 否 | 关键词搜索 |
| rating | string | 否 | 评分筛选,枚举 helpful/not_helpful |
| export | string | 否 | 设为 "csv" 时返回 CSV 文件流 |
**响应JSON 模式)**
```json
{
"code": 0,
"data": {
"total": 1200,
"items": [
{
"id": "msg-001",
"user_id": "user-001",
"username": "张三",
"question": "重疾险等待期多少天?",
"answer": "等待期为合同生效之日起90天。",
"sources": ["XX重疾险条款.md"],
"rating": "helpful",
"created_at": "2026-05-31T10:00:00Z"
}
]
}
}
```
**响应CSV 导出)**:当 `export=csv` 时返回文件流
```
Content-Type: text/csv
Content-Disposition: attachment; filename="chat_logs_202605.csv"
```
### A7.1.2 导出对话记录
| 项 | 值 |
|----|---|
| URL | `GET /api/admin/logs/chat/export` |
| 认证 | 需要(管理员) |
| 实现 | 自研(调 BaoDan |
**查询参数**:同 A7.1.1 的筛选参数
**响应**:返回 CSV 文件流
```
Content-Type: text/csv
Content-Disposition: attachment; filename="chat_logs_202606.csv"
```
### A7.1.3 系统操作日志
| 项 | 值 |
|----|---|
| URL | `GET /api/admin/logs/system` |
| 认证 | 需要(超级管理员) |
| 实现 | 自研 |
**查询参数**`page`、`page_size`、`action`、`user_id`
**响应**
```json
{
"code": 0,
"data": {
"total": 200,
"items": [
{
"id": "log-001",
"action": "login",
"user_id": "user-001",
"username": "张三",
"ip": "192.168.1.100",
"device": "Chrome/120 Windows",
"detail": "企微 OAuth 登录",
"created_at": "2026-05-31T09:00:00Z"
}
]
}
}
```
---
## 十、统计报表A8
### A8.1.1 使用概览
| 项 | 值 |
|----|---|
| URL | `GET /api/stats/overview` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
**响应**
```json
{
"code": 0,
"data": {
"today_chats": 45,
"active_users": 12,
"kb_hit_rate": 0.87,
"total_documents": 1500
}
}
```
### A8.1.2 趋势数据
| 项 | 值 |
|----|---|
| URL | `GET /api/stats/trend` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
**查询参数**`metric`(如 chat_count、`start_date`、`end_date`、`granularity`day/week/month
**响应**
```json
{
"code": 0,
"data": {
"metric": "chat_count",
"granularity": "day",
"data": [
{ "date": "2026-05-01", "value": 45 },
{ "date": "2026-05-02", "value": 62 }
]
}
}
```
### A8.1.3 知识库健康度
| 项 | 值 |
|----|---|
| URL | `GET /api/stats/kb-health` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
**查询参数**`days`
**响应**
```json
{
"code": 0,
"data": {
"hot_questions": [{"question": "重疾险等待期多少天", "count": 230}],
"missed_questions": [{"question": "XX新产品费率", "count": 45, "handled": false}],
"coverage": {
"寿险": {"doc_count": 320, "status": "completed"},
"重疾险": {"doc_count": 280, "status": "completed"}
}
}
}
```
### A8.1.4 Token 消耗统计
| 项 | 值 |
|----|---|
| URL | `GET /api/stats/token-cost` |
| 认证 | 需要(管理员) |
| 实现 | 自研 |
**查询参数**`start_date`、`end_date`、`group_by`model
**响应**
```json
{
"code": 0,
"data": {
"total_tokens": 2500000,
"total_cost_usd": 12.5,
"by_model": [
{"model": "deepseek-chat", "input_tokens": 1500000, "output_tokens": 500000, "cost_usd": 10.0}
],
"daily_trend": [
{"date": "2026-05-01", "tokens": 80000, "cost_usd": 0.4}
]
}
}
```
---
## 十一、接口清单汇总
| # | 方法 | URL | 认证 | 实现 | 对应功能 |
|---|------|-----|:---:|------|---------|
| 1 | GET | /api/health | 否 | 自研 | 健康检查 |
| 2 | GET | /api/wecom/callback | 否 | 自研+企微 | 企微回调验证 |
| 3 | POST | /api/wecom/callback | 否 | 自研+企微 | 企微消息接收 |
| 4 | GET | /api/wecom/oauth | 否 | 自研 | OAuth 入口 |
| 5 | GET | /api/wecom/oauth/callback | 否 | 自研 | OAuth 回调 |
| 6 | POST | /api/auth/wework-login | 否 | 自研(调BaoDan) | 企微登录 |
| 7 | POST | /api/auth/password-login | 否 | 自研(调BaoDan) | 账密登录 |
| 8 | POST | /api/auth/refresh-token | 是 | 自研(调BaoDan) | 刷新Token |
| 9 | POST | /api/auth/logout | 是 | 自研 | 退出登录 |
| 10 | POST | /api/chat/message | 是 | 自研(调BaoDan) | 发送消息(SSE) |
| 11 | GET | /api/chat/sessions | 是 | 自研(调BaoDan) | 会话列表 |
| 12 | POST | /api/chat/sessions | 是 | 自研(调BaoDan) | 创建会话 |
| 13 | DELETE | /api/chat/sessions/{id} | 是 | 自研(调BaoDan) | 删除会话 |
| 14 | GET | /api/chat/sessions/{id}/messages | 是 | 自研(调BaoDan) | 消息记录 |
| 15 | POST | /api/chat/messages/{id}/feedback | 是 | 自研(调BaoDan) | 提交反馈 |
| 16 | POST | /api/chat/suggest | 是 | 自研 | 推荐追问 |
| 17 | POST | /api/retrieval/search | 是 | 自研(调BaoDan) | 向量检索 |
| 18 | POST | /api/recommend/generate | 是 | 自研(调BaoDan) | 生成推荐方案 |
| 19 | GET | /api/recommend/generate/{id} | 是 | 自研 | 查询方案状态 |
| 20 | POST | /api/recommend/{id}/export | 是 | 自研 | 方案导出 |
| 21 | POST | /api/recommend/{id}/share | 是 | 自研 | 生成分享链接 |
| 22 | POST | /api/kb/documents/upload | 是 | 自研(调BaoDan) | 上传文档 |
| 23 | GET | /api/kb/documents | 是 | 自研(调BaoDan) | 文档列表 |
| 24 | GET | /api/kb/documents/{id}/status | 是 | 自研(调BaoDan) | 文档处理状态 |
| 25 | POST | /api/kb/documents/{id}/retry | 是 | 自研(调BaoDan) | 重试文档 |
| 26 | PATCH | /api/kb/documents/{id} | 是 | 自研(调BaoDan) | 更新元数据 |
| 27 | DELETE | /api/kb/documents/{id} | 是 | 自研(调BaoDan) | 删除文档 |
| 28 | GET | /api/kb/datasources | 是 | 自研 | 数据源列表 |
| 29 | POST | /api/kb/datasources | 是 | 自研 | 新建数据源 |
| 30 | POST | /api/kb/datasources/{id}/sync | 是 | 自研 | 手动同步 |
| 31 | GET | /api/kb/datasources/{id}/logs | 是 | 自研 | 同步日志 |
| 32 | GET/POST/PUT/DELETE | /api/admin/users | 管理员 | 自研(调BaoDan) | 用户管理 |
| 33 | POST | /api/admin/users/batch-import | 超管 | 自研 | 批量导入 |
| 34 | GET/POST/PUT/DELETE | /api/admin/roles | 超管 | 自研 | 角色管理 |
| 35 | GET/POST/PUT | /api/admin/llm-configs | 超管 | 自研(调BaoDan) | LLM配置 |
| 36 | POST | /api/admin/llm-configs/{id}/ping | 管理员 | 自研(调BaoDan) | 连通性测试 |
| 37 | GET/POST/PUT | /api/admin/prompts | 管理员 | 自研(调BaoDan) | Prompt管理 |
| 38 | POST | /api/admin/prompts/test | 管理员 | 自研(调BaoDan) | Prompt测试 |
| 39 | GET | /api/admin/logs/chat | 管理员 | 自研(调BaoDan) | 问答日志 |
| 40 | GET | /api/admin/logs/chat/export | 管理员 | 自研(调BaoDan) | 导出对话记录 |
| 41 | GET | /api/admin/logs/system | 超管 | 自研 | 系统日志 |
| 42 | GET | /api/stats/overview | 管理员 | 自研 | 使用概览 |
| 43 | GET | /api/stats/trend | 管理员 | 自研 | 趋势数据 |
| 44 | GET | /api/stats/kb-health | 管理员 | 自研 | 知识库健康度 |
| 45 | GET | /api/stats/token-cost | 管理员 | 自研 | Token消耗 |
| 46 | POST | /api/wecom/callback企微内部 | - | - | 同 #3 |
| 47 | POST | /api/recommend/generateBaoDan内部 | - | - | 同 #18 |
> 注:#46 和 #47 是企微/BaoDan 侧视角的接口,实际为同一端点。有效独立接口为 **45 个**。