ai-robot-core/AI中台对接文档.md

512 lines
13 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.

# AI 中台对接文档
## 1. 概述
本文档描述 Python AI 中台对渠道侧Java 主框架)暴露的 HTTP 接口规范,用于智能客服对话生成和服务健康检查。
### 1.1 服务信息
- **服务名称**: AI Service (Python AI 中台)
- **服务地址**: `http://ai-service:8080`
- **协议**: HTTP/1.1
- **数据格式**: JSON / SSE (Server-Sent Events)
- **字符编码**: UTF-8
- **契约版本**: v1.1.0
### 1.2 核心能力
- ✅ 智能对话生成(基于 LLM + RAG
- ✅ 多租户隔离(基于 `X-Tenant-Id`
- ✅ 会话上下文管理(基于 `sessionId`
- ✅ 流式/非流式双模式输出
- ✅ 置信度评估与转人工建议
- ✅ 服务健康检查
---
## 2. 认证与租户隔离
### 2.1 API Key 认证(必填)
所有接口请求(除健康检查外)必须在 HTTP Header 中携带 API Key
```http
X-API-Key: <your_api_key>
```
**说明**
- API Key 用于身份认证和访问控制
- 缺失或无效的 API Key 将返回 `401 Unauthorized`
- API Key 由 AI 中台管理员分配,请妥善保管
- 以下路径无需 API Key`/health`、`/ai/health`、`/docs`
### 2.2 租户标识(必填)
所有接口请求必须在 HTTP Header 中携带租户 ID
```http
X-Tenant-Id: <tenant_id>
```
**租户 ID 格式规范**`name@ash@year`
示例:
- `szmp@ash@2026` - 深圳某项目 2026 年
- `abc123@ash@2025` - ABC 项目 2025 年
**说明**
- 租户 ID 用于数据隔离(知识库、会话历史、配置等)
- 缺失或格式错误的租户 ID 将返回 `400 Bad Request`
- 不同租户的数据完全隔离,不可跨租户访问
- 租户不存在时会自动创建
---
## 3. 接口列表
| 接口路径 | 方法 | 功能 | 响应模式 |
|---------|------|------|---------|
| `/ai/chat` | POST | 生成 AI 回复 | JSON / SSE |
| `/ai/health` | GET | 健康检查 | JSON |
---
## 4. 接口详细说明
### 4.1 生成 AI 回复
**接口路径**: `POST /ai/chat`
**功能描述**: 根据用户消息和会话历史生成 AI 回复,支持 RAG 检索增强、上下文管理、置信度评估。
#### 4.1.1 请求参数
**Headers**:
```http
Content-Type: application/json
X-API-Key: <your_api_key>
X-Tenant-Id: <tenant_id>
Accept: application/json # 或 text/event-stream流式输出
```
**Body** (JSON):
| 字段 | 类型 | 必填 | 说明 |
|-----|------|------|------|
| `sessionId` | string | ✅ | 会话 ID用于关联同一会话的对话历史 |
| `currentMessage` | string | ✅ | 当前用户消息内容 |
| `channelType` | string | ✅ | 渠道类型,枚举值:`wechat`、`douyin`、`jd` |
| `history` | array | ❌ | 历史消息列表可选AI 中台会自动管理会话历史) |
| `metadata` | object | ❌ | 扩展元数据(可选) |
**history 数组元素结构**:
```json
{
"role": "user | assistant",
"content": "消息内容"
}
```
**请求示例**:
```json
{
"sessionId": "kf_001_wx123456_1708765432000",
"currentMessage": "我想了解产品价格",
"channelType": "wechat",
"metadata": {
"channelUserId": "wx123456",
"extra": "..."
}
}
```
#### 4.1.2 响应格式
##### 模式 1: JSON 响应(非流式)
**状态码**: `200 OK`
**响应体**:
```json
{
"reply": "您好,我们的产品价格根据套餐不同有所差异...",
"confidence": 0.92,
"shouldTransfer": false,
"transferReason": null,
"metadata": {
"retrieval_count": 3,
"rag_enabled": true
}
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----|------|------|------|
| `reply` | string | ✅ | AI 生成的回复内容 |
| `confidence` | number | ✅ | 置信度评分0.0-1.0),越高表示回答越可靠 |
| `shouldTransfer` | boolean | ✅ | 是否建议转人工true=建议转人工) |
| `transferReason` | string | ❌ | 转人工原因(可选) |
| `metadata` | object | ❌ | 响应元数据(可选) |
##### 模式 2: SSE 流式响应
**触发条件**: 请求头包含 `Accept: text/event-stream`
**响应头**:
```http
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
```
**事件流格式**:
1. **增量消息事件** (可多次发送)
```
event: message
data: {"delta": "您好,"}
event: message
data: {"delta": "我们的产品"}
```
2. **最终结果事件** (发送一次后关闭连接)
```
event: final
data: {"reply": "完整回复内容", "confidence": 0.92, "shouldTransfer": false}
```
3. **错误事件** (发生错误时发送)
```
event: error
data: {"code": "INTERNAL_ERROR", "message": "错误描述"}
```
**事件序列保证**:
- `message*` (0 或多次) → `final` (1 次) → 连接关闭
-`message*` (0 或多次) → `error` (1 次) → 连接关闭
#### 4.1.3 错误响应
**401 Unauthorized** - 认证失败
```json
{
"code": "UNAUTHORIZED",
"message": "Missing required header: X-API-Key",
"details": []
}
```
**400 Bad Request** - 请求参数错误
```json
{
"code": "INVALID_REQUEST",
"message": "缺少必填字段: sessionId",
"details": []
}
```
**400 Bad Request** - 租户 ID 格式错误
```json
{
"code": "INVALID_TENANT_ID",
"message": "Invalid tenant ID format. Expected: name@ash@year (e.g., szmp@ash@2026)",
"details": []
}
```
**500 Internal Server Error** - 服务内部错误
```json
{
"code": "INTERNAL_ERROR",
"message": "LLM 调用失败",
"details": []
}
```
**503 Service Unavailable** - 服务不可用
```json
{
"code": "SERVICE_UNAVAILABLE",
"message": "向量数据库连接失败",
"details": []
}
```
---
### 4.2 健康检查
**接口路径**: `GET /ai/health`
**功能描述**: 检查 AI 服务是否正常运行,用于服务监控和负载均衡健康探测。
#### 4.2.1 请求参数
无需请求参数,无需认证头。
#### 4.2.2 响应格式
**200 OK** - 服务正常
```json
{
"status": "healthy"
}
```
**503 Service Unavailable** - 服务不健康
```json
{
"status": "unhealthy"
}
```
---
## 5. 调用示例
### 5.1 Java 调用示例(非流式)
```java
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
public class AIServiceClient {
private final RestTemplate restTemplate;
private final String aiServiceUrl = "http://ai-service:8080";
private final String apiKey = "your_api_key_here";
public ChatResponse generateReply(String tenantId, ChatRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-API-Key", apiKey);
headers.set("X-Tenant-Id", tenantId);
HttpEntity<ChatRequest> entity = new HttpEntity<>(request, headers);
ResponseEntity<ChatResponse> response = restTemplate.postForEntity(
aiServiceUrl + "/ai/chat",
entity,
ChatResponse.class
);
return response.getBody();
}
}
```
### 5.2 Java 调用示例(流式)
```java
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
public class AIServiceStreamClient {
private final WebClient webClient;
private final String apiKey = "your_api_key_here";
public Flux<ServerSentEvent<String>> generateReplyStream(
String tenantId,
ChatRequest request
) {
return webClient.post()
.uri("/ai/chat")
.header("X-API-Key", apiKey)
.header("X-Tenant-Id", tenantId)
.header("Accept", "text/event-stream")
.bodyValue(request)
.retrieve()
.bodyToFlux(ServerSentEvent.class);
}
}
```
### 5.3 cURL 调用示例
```bash
# 非流式调用
curl -X POST http://ai-service:8080/ai/chat \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-H "X-Tenant-Id: szmp@ash@2026" \
-d '{
"sessionId": "kf_001_wx123456_1708765432000",
"currentMessage": "我想了解产品价格",
"channelType": "wechat"
}'
# 流式调用
curl -X POST http://ai-service:8080/ai/chat \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-H "X-Tenant-Id: szmp@ash@2026" \
-H "Accept: text/event-stream" \
-d '{
"sessionId": "kf_001_wx123456_1708765432000",
"currentMessage": "我想了解产品价格",
"channelType": "wechat"
}'
# 健康检查(无需认证)
curl http://ai-service:8080/ai/health
```
---
## 6. 业务逻辑说明
### 6.1 会话管理
- **会话标识**: `sessionId` 用于唯一标识一个对话会话
- **自动持久化**: AI 中台会自动保存会话历史,无需调用方每次传递完整历史
- **可选历史**: 调用方可通过 `history` 字段提供外部历史AI 中台会合并处理
- **租户隔离**: 相同 `sessionId` 在不同 `tenantId` 下视为不同会话
### 6.2 RAG 检索增强
- **自动触发**: AI 中台会根据用户问题自动判断是否需要检索知识库
- **多知识库**: 支持按知识库类型产品知识、FAQ、话术模板等分类检索
- **置信度评估**: 检索结果质量会影响 `confidence` 评分
- **兜底策略**: 检索失败或无结果时AI 会基于通用知识回答并降低置信度
### 6.3 转人工建议
`shouldTransfer` 字段由以下因素决定:
- ✅ 置信度低于阈值(默认 0.6
- ✅ 检索无结果或结果质量差
- ✅ 用户明确要求人工服务
- ✅ 意图识别命中"转人工"规则
**注意**: `shouldTransfer=true` 仅为建议最终是否转人工由调用方Java 主框架)决策。
### 6.4 意图识别与规则引擎
- **前置处理**: 用户消息会先经过意图识别
- **固定回复**: 命中固定规则时直接返回预设话术(跳过 LLM 调用)
- **话术流程**: 命中流程规则时进入多轮引导对话
- **定向检索**: 命中 RAG 规则时使用指定知识库检索
### 6.5 输出护栏
- **禁词过滤**: AI 回复会自动过滤禁词(竞品名称、敏感词等)
- **替换策略**: 支持星号替换、文本替换、整条拦截三种策略
- **行为约束**: Prompt 中注入行为规则(如"不承诺具体赔偿金额"
---
## 7. 性能与限制
### 7.1 性能指标
| 指标 | 非流式 | 流式 |
|-----|-------|------|
| 首字响应时间 | 1-3 秒 | 200-500 毫秒 |
| 完整响应时间 | 2-5 秒 | 3-8 秒 |
| 并发支持 | 100+ QPS | 50+ QPS |
### 7.2 限制说明
- **消息长度**: 单条消息最大 4000 字符
- **历史长度**: 建议历史消息不超过 20 轮AI 中台会自动截断)
- **超时设置**: 建议调用方设置 10 秒超时非流式、30 秒超时(流式)
- **重试策略**: 503 错误建议指数退避重试500 错误建议降级处理
---
## 8. 错误码参考
| 错误码 | HTTP 状态码 | 说明 | 处理建议 |
|-------|-----------|------|---------|
| `UNAUTHORIZED` | 401 | 认证失败(缺少或无效 API Key | 检查 X-API-Key 请求头 |
| `INVALID_REQUEST` | 400 | 请求参数错误 | 检查必填字段和参数格式 |
| `MISSING_TENANT_ID` | 400 | 缺少租户 ID | 添加 X-Tenant-Id 请求头 |
| `INVALID_TENANT_ID` | 400 | 租户 ID 格式错误 | 使用正确格式name@ash@year |
| `INTERNAL_ERROR` | 500 | 服务内部错误 | 降级处理或重试 |
| `LLM_ERROR` | 500 | LLM 调用失败 | 降级处理或重试 |
| `SERVICE_UNAVAILABLE` | 503 | 服务不可用 | 指数退避重试 |
| `QDRANT_ERROR` | 503 | 向量库不可用 | 指数退避重试 |
| `STREAMING_ERROR` | 200 (SSE) | 流式传输错误 | 关闭连接并重试 |
---
## 9. 最佳实践
### 9.1 API Key 管理
- API Key 由 AI 中台管理员通过管理后台分配
- 建议为不同环境(开发/测试/生产)使用不同的 API Key
- API Key 应存储在配置文件或环境变量中,不要硬编码
- 定期轮换 API Key 以提高安全性
### 9.2 会话 ID 生成规范
建议格式: `{业务前缀}_{租户ID}_{渠道用户ID}_{时间戳}`
示例: `kf_001_wx123456_1708765432000`
### 9.3 流式 vs 非流式选择
- **流式**: 适用于 Web/App 实时对话场景,用户体验更好
- **非流式**: 适用于批量处理、异步任务、API 集成场景
### 9.4 降级策略建议
```java
public ChatResponse generateReplyWithFallback(String tenantId, ChatRequest request) {
try {
return aiServiceClient.generateReply(tenantId, request);
} catch (ServiceUnavailableException e) {
// 降级策略 1: 返回固定话术
return ChatResponse.builder()
.reply("抱歉,当前咨询量较大,请稍后再试或转人工服务。")
.confidence(0.0)
.shouldTransfer(true)
.build();
} catch (Exception e) {
// 降级策略 2: 直接转人工
return ChatResponse.builder()
.reply("系统繁忙,正在为您转接人工客服...")
.confidence(0.0)
.shouldTransfer(true)
.transferReason("AI 服务异常")
.build();
}
}
```
### 9.5 监控指标建议
- ✅ 接口响应时间P50/P95/P99
- ✅ 接口成功率
- ✅ 置信度分布
- ✅ 转人工率
- ✅ 错误码分布
---
## 10. 变更日志
| 版本 | 日期 | 变更内容 |
|-----|------|---------|
| v1.1.0 | 2026-02-27 | 新增流式输出支持、意图识别、输出护栏 |
| v1.0.0 | 2026-02-20 | 初始版本,支持基础对话生成和健康检查 |
---
## 11. 联系方式
- **技术支持**: AI 中台开发团队
- **问题反馈**: 提交 Issue 到项目仓库
- **文档更新**: 参考 `spec/ai-service/openapi.provider.yaml`
---
**文档生成时间**: 2026-02-27
**契约版本**: v1.1.0
**维护状态**: ✅ 活跃维护