Files
AI-VideoAssistant/api/docs/history-records.md
2026-02-08 13:16:53 +08:00

465 lines
9.3 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.
# 历史记录 (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 字段) |