Add docs for api backend
This commit is contained in:
464
api/docs/history-records.md
Normal file
464
api/docs/history-records.md
Normal file
@@ -0,0 +1,464 @@
|
||||
# 历史记录 (History Records) API
|
||||
|
||||
历史记录 API 用于管理通话记录和对话历史。
|
||||
|
||||
## 基础信息
|
||||
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| Base URL | `/api/v1/history` |
|
||||
| 认证方式 | Bearer Token (预留) |
|
||||
|
||||
---
|
||||
|
||||
## 数据模型
|
||||
|
||||
### CallRecord
|
||||
|
||||
```typescript
|
||||
interface CallRecord {
|
||||
id: string; // 通话记录ID
|
||||
user_id: number; // 所属用户ID
|
||||
assistant_id?: string; // 关联助手ID
|
||||
source: string; // 来源: "debug" | "external"
|
||||
status: string; // 状态: "connected" | "missed" | "failed"
|
||||
started_at: string; // 开始时间 ISO8601
|
||||
ended_at?: string; // 结束时间 ISO8601
|
||||
duration_seconds?: int; // 通话时长(秒)
|
||||
summary?: string; // 通话摘要
|
||||
cost?: number; // 费用
|
||||
metadata?: object; // 元数据
|
||||
created_at: string; // 创建时间
|
||||
}
|
||||
```
|
||||
|
||||
### TranscriptSegment
|
||||
|
||||
```typescript
|
||||
interface TranscriptSegment {
|
||||
turn_index: int; // 对话轮次
|
||||
speaker: string; // 说话者: "human" | "ai"
|
||||
content: string; // 转写内容
|
||||
confidence?: float; // 置信度 0-1
|
||||
start_ms: int; // 开始时间(毫秒)
|
||||
end_ms: int; // 结束时间(毫秒)
|
||||
duration_ms?: int; // 持续时间(毫秒)
|
||||
audio_url?: string; // 音频URL
|
||||
emotion?: string; // 情绪标签
|
||||
}
|
||||
```
|
||||
|
||||
### InteractionDetail
|
||||
|
||||
```typescript
|
||||
interface InteractionDetail {
|
||||
role: "user" | "assistant"; // 角色
|
||||
content: string; // 文本内容或转写文本
|
||||
audio_url?: string; // 音频URL
|
||||
image_urls?: string[]; // 图片URL列表(视频场景)
|
||||
timestamp: string; // 时间戳
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 端点
|
||||
|
||||
### 1. 获取通话记录列表
|
||||
|
||||
```http
|
||||
GET /api/v1/history
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| assistant_id | string | 否 | 过滤助手ID |
|
||||
| status | string | 否 | 过滤状态: "connected" \| "missed" \| "failed" |
|
||||
| source | string | 否 | 过滤来源: "debug" \| "external" |
|
||||
| start_date | string | 否 | 开始日期 ISO8601 |
|
||||
| end_date | string | 否 | 结束日期 ISO8601 |
|
||||
| page | int | 否 | 页码,默认 1 |
|
||||
| limit | int | 否 | 每页数量,默认 20 |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 150,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"list": [
|
||||
{
|
||||
"id": "call_001",
|
||||
"user_id": 1,
|
||||
"assistant_id": "abc12345",
|
||||
"source": "debug",
|
||||
"status": "connected",
|
||||
"started_at": "2024-01-15T14:30:00Z",
|
||||
"ended_at": "2024-01-15T14:33:00Z",
|
||||
"duration_seconds": 180,
|
||||
"summary": "用户咨询产品A的售后服务",
|
||||
"cost": 0.05,
|
||||
"created_at": "2024-01-15T14:30:00Z"
|
||||
},
|
||||
{
|
||||
"id": "call_002",
|
||||
"user_id": 1,
|
||||
"assistant_id": "abc12345",
|
||||
"source": "external",
|
||||
"status": "missed",
|
||||
"started_at": "2024-01-15T14:00:00Z",
|
||||
"duration_seconds": 0,
|
||||
"created_at": "2024-01-15T14:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 获取通话详情
|
||||
|
||||
```http
|
||||
GET /api/v1/history/{call_id}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "call_001",
|
||||
"user_id": 1,
|
||||
"assistant_id": "abc12345",
|
||||
"source": "debug",
|
||||
"status": "connected",
|
||||
"started_at": "2024-01-15T14:30:00Z",
|
||||
"ended_at": "2024-01-15T14:33:00Z",
|
||||
"duration_seconds": 180,
|
||||
"summary": "用户咨询产品A的售后服务",
|
||||
"cost": 0.05,
|
||||
"metadata": {
|
||||
"browser": "Chrome",
|
||||
"os": "Windows"
|
||||
},
|
||||
"transcripts": [
|
||||
{
|
||||
"turn_index": 0,
|
||||
"speaker": "human",
|
||||
"content": "您好,我想咨询一下产品A的售后服务",
|
||||
"confidence": 0.98,
|
||||
"start_ms": 0,
|
||||
"end_ms": 3500,
|
||||
"duration_ms": 3500,
|
||||
"audio_url": "https://storage.example.com/audio/call_001/turn_0.mp3"
|
||||
},
|
||||
{
|
||||
"turn_index": 1,
|
||||
"speaker": "ai",
|
||||
"content": "您好!产品A享有7天无理由退货和一年质保服务。请问您遇到了什么问题?",
|
||||
"confidence": 0.95,
|
||||
"start_ms": 4000,
|
||||
"end_ms": 12000,
|
||||
"duration_ms": 8000,
|
||||
"audio_url": "https://storage.example.com/audio/call_001/turn_1.mp3"
|
||||
},
|
||||
{
|
||||
"turn_index": 2,
|
||||
"speaker": "human",
|
||||
"content": "我发现产品A有一个功能坏了",
|
||||
"confidence": 0.92,
|
||||
"start_ms": 13000,
|
||||
"end_ms": 18000,
|
||||
"duration_ms": 5000,
|
||||
"audio_url": "https://storage.example.com/audio/call_001/turn_2.mp3"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 创建通话记录
|
||||
|
||||
```http
|
||||
POST /api/v1/history
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 1,
|
||||
"assistant_id": "abc12345",
|
||||
"source": "debug"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "call_new001",
|
||||
"user_id": 1,
|
||||
"assistant_id": "abc12345",
|
||||
"source": "debug",
|
||||
"status": "connected",
|
||||
"started_at": "2024-01-15T15:00:00Z",
|
||||
"created_at": "2024-01-15T15:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 更新通话记录
|
||||
|
||||
```http
|
||||
PUT /api/v1/history/{call_id}
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "connected",
|
||||
"summary": "用户咨询产品A的售后服务,已引导用户提交工单",
|
||||
"duration_seconds": 180,
|
||||
"ended_at": "2024-01-15T14:33:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. 删除通话记录
|
||||
|
||||
```http
|
||||
DELETE /api/v1/history/{call_id}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 添加转写片段
|
||||
|
||||
```http
|
||||
POST /api/v1/history/{call_id}/transcripts
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"turn_index": 3,
|
||||
"speaker": "ai",
|
||||
"content": "好的,我已经为您创建了工单,编号 #12345,请保持电话畅通,我们的客服人员会在24小时内联系您。",
|
||||
"confidence": 0.96,
|
||||
"start_ms": 20000,
|
||||
"end_ms": 28000,
|
||||
"duration_ms": 8000,
|
||||
"emotion": "neutral"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 100,
|
||||
"turn_index": 3,
|
||||
"speaker": "ai",
|
||||
"content": "好的,我已经为您创建了工单...",
|
||||
"confidence": 0.96,
|
||||
"start_ms": 20000,
|
||||
"end_ms": 28000,
|
||||
"duration_ms": 8000,
|
||||
"audio_url": "https://storage.example.com/audio/call_001/turn_3.mp3",
|
||||
"emotion": "neutral"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. 获取音频
|
||||
|
||||
```http
|
||||
GET /api/v1/history/{call_id}/audio/{turn_index}
|
||||
```
|
||||
|
||||
**Response:** 重定向到音频文件 URL
|
||||
|
||||
---
|
||||
|
||||
### 8. 搜索通话记录
|
||||
|
||||
```http
|
||||
GET /api/v1/history/search
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| q | string | 是 | 搜索关键词 |
|
||||
| page | int | 否 | 页码 |
|
||||
| limit | int | 否 | 每页数量 |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 5,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"list": [
|
||||
{
|
||||
"id": "call_001",
|
||||
"started_at": "2024-01-15T14:30:00Z",
|
||||
"matched_content": "用户咨询产品A的售后服务"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. 获取统计信息
|
||||
|
||||
```http
|
||||
GET /api/v1/history/stats
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| start_date | string | 否 | 开始日期 |
|
||||
| end_date | string | 否 | 结束日期 |
|
||||
| assistant_id | string | 否 | 助手ID |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"total_calls": 150,
|
||||
"connected_calls": 135,
|
||||
"missed_calls": 15,
|
||||
"failed_calls": 0,
|
||||
"avg_duration_seconds": 180,
|
||||
"total_cost": 7.50,
|
||||
"by_status": {
|
||||
"connected": 135,
|
||||
"missed": 15,
|
||||
"failed": 0
|
||||
},
|
||||
"by_source": {
|
||||
"debug": 100,
|
||||
"external": 50
|
||||
},
|
||||
"daily_trend": [
|
||||
{
|
||||
"date": "2024-01-15",
|
||||
"calls": 20,
|
||||
"connected": 18,
|
||||
"avg_duration": 175
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 推荐的 Schema 定义
|
||||
|
||||
```python
|
||||
# ============ Call Record ============
|
||||
class CallRecordSource(str, Enum):
|
||||
DEBUG = "debug"
|
||||
EXTERNAL = "external"
|
||||
|
||||
class CallRecordStatus(str, Enum):
|
||||
CONNECTED = "connected"
|
||||
MISSED = "missed"
|
||||
FAILED = "failed"
|
||||
|
||||
class CallRecordBase(BaseModel):
|
||||
assistant_id: Optional[str] = None
|
||||
source: str = "debug"
|
||||
|
||||
class CallRecordCreate(CallRecordBase):
|
||||
pass
|
||||
|
||||
class CallRecordUpdate(BaseModel):
|
||||
status: Optional[str] = None
|
||||
summary: Optional[str] = None
|
||||
duration_seconds: Optional[int] = None
|
||||
ended_at: Optional[str] = None
|
||||
cost: Optional[float] = None
|
||||
metadata: Optional[dict] = None
|
||||
|
||||
class TranscriptSegment(BaseModel):
|
||||
turn_index: int
|
||||
speaker: str # "human" | "ai"
|
||||
content: str
|
||||
confidence: Optional[float] = None
|
||||
start_ms: int
|
||||
end_ms: int
|
||||
duration_ms: Optional[int] = None
|
||||
emotion: Optional[str] = None
|
||||
|
||||
class CallRecordOut(BaseModel):
|
||||
id: str
|
||||
user_id: int
|
||||
assistant_id: Optional[str] = None
|
||||
source: str
|
||||
status: str
|
||||
started_at: str
|
||||
ended_at: Optional[str] = None
|
||||
duration_seconds: Optional[int] = None
|
||||
summary: Optional[str] = None
|
||||
cost: float = 0.0
|
||||
metadata: dict = {}
|
||||
created_at: datetime
|
||||
transcripts: List[TranscriptSegment] = []
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class TranscriptCreate(BaseModel):
|
||||
turn_index: int
|
||||
speaker: str
|
||||
content: str
|
||||
confidence: Optional[float] = None
|
||||
start_ms: int
|
||||
end_ms: int
|
||||
duration_ms: Optional[int] = None
|
||||
emotion: Optional[str] = None
|
||||
|
||||
class TranscriptOut(TranscriptCreate):
|
||||
id: int
|
||||
audio_url: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class HistoryStats(BaseModel):
|
||||
total_calls: int
|
||||
connected_calls: int
|
||||
missed_calls: int
|
||||
failed_calls: int
|
||||
avg_duration_seconds: float
|
||||
total_cost: float
|
||||
by_status: dict
|
||||
by_source: dict
|
||||
daily_trend: List[dict]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Web 端对应接口映射
|
||||
|
||||
| Web Type | API Endpoint |
|
||||
|----------|--------------|
|
||||
| CallLog (list) | `GET /api/v1/history` |
|
||||
| CallLog (detail) | `GET /api/v1/history/{id}` |
|
||||
| InteractionDetail | `GET /api/v1/history/{id}` (transcripts 字段) |
|
||||
Reference in New Issue
Block a user