nanoClaw/docs/Design.md

644 lines
14 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 设计
## API 总览
### 会话管理
| 方法 | 路径 | 说明 |
| -------- | ------------------------ | ------ |
| `POST` | `/api/conversations` | 创建会话 |
| `GET` | `/api/conversations` | 获取会话列表 |
| `GET` | `/api/conversations/:id` | 获取会话详情 |
| `PATCH` | `/api/conversations/:id` | 更新会话 |
| `DELETE` | `/api/conversations/:id` | 删除会话 |
### 消息管理
| 方法 | 路径 | 说明 |
| -------- | --------------------------------------------- | ------------------------- |
| `GET` | `/api/conversations/:id/messages` | 获取消息列表 |
| `POST` | `/api/conversations/:id/messages` | 发送消息(对话补全,支持 `stream` 流式) |
| `DELETE` | `/api/conversations/:id/messages/:message_id` | 删除消息 |
### 模型与工具
| 方法 | 路径 | 说明 |
| ------ | ------------- | -------- |
| `GET` | `/api/models` | 获取模型列表 |
| `GET` | `/api/tools` | 获取工具列表 |
### 统计信息
| 方法 | 路径 | 说明 |
| ------ | -------------------- | ---------------- |
| `GET` | `/api/stats/tokens` | 获取 Token 使用统计 |
---
## API 接口
### 1. 会话管理
#### 创建会话
```
POST /api/conversations
```
**请求体:**
```json
{
"title": "新对话",
"model": "glm-5",
"system_prompt": "你是一个有帮助的助手",
"temperature": 1.0,
"max_tokens": 65536,
"thinking_enabled": false
}
```
**响应:**
```json
{
"code": 0,
"data": {
"id": "conv_abc123",
"title": "新对话",
"model": "glm-5",
"system_prompt": "你是一个有帮助的助手",
"temperature": 1.0,
"max_tokens": 65536,
"thinking_enabled": false,
"created_at": "2026-03-24T10:00:00Z",
"updated_at": "2026-03-24T10:00:00Z"
}
}
```
#### 获取会话列表
```
GET /api/conversations?cursor=conv_abc123&limit=20
```
| 参数 | 类型 | 说明 |
| -------- | ------- | ----------------- |
| `cursor` | string | 分页游标,为空取首页 |
| `limit` | integer | 每页数量,默认 20最大 100 |
**响应:**
```json
{
"code": 0,
"data": {
"items": [
{
"id": "conv_abc123",
"title": "新对话",
"model": "glm-5",
"created_at": "2026-03-24T10:00:00Z",
"updated_at": "2026-03-24T10:05:00Z",
"message_count": 6
}
],
"next_cursor": "conv_def456",
"has_more": true
}
}
```
#### 获取会话详情
```
GET /api/conversations/:id
```
**响应:**
```json
{
"code": 0,
"data": {
"id": "conv_abc123",
"title": "新对话",
"model": "glm-5",
"system_prompt": "你是一个有帮助的助手",
"temperature": 1.0,
"max_tokens": 65536,
"thinking_enabled": false,
"created_at": "2026-03-24T10:00:00Z",
"updated_at": "2026-03-24T10:05:00Z"
}
}
```
#### 更新会话
```
PATCH /api/conversations/:id
```
**请求体(仅传需更新的字段):**
```json
{
"title": "修改后的标题",
"system_prompt": "新的系统提示词",
"temperature": 0.8
}
```
**响应:** 同获取会话详情
#### 删除会话
```
DELETE /api/conversations/:id
```
**响应:**
```json
{
"code": 0,
"message": "deleted"
}
```
---
### 2. 消息管理
#### 获取消息列表
```
GET /api/conversations/:id/messages?cursor=msg_001&limit=50
```
| 参数 | 类型 | 说明 |
| -------- | ------- | ----------------- |
| `cursor` | string | 分页游标 |
| `limit` | integer | 每页数量,默认 50最大 100 |
**响应:**
```json
{
"code": 0,
"data": {
"items": [
{
"id": "msg_001",
"conversation_id": "conv_abc123",
"role": "user",
"content": "你好",
"token_count": 2,
"thinking_content": null,
"tool_calls": null,
"created_at": "2026-03-24T10:00:00Z"
},
{
"id": "msg_002",
"conversation_id": "conv_abc123",
"role": "assistant",
"content": "你好!有什么可以帮你的?",
"token_count": 15,
"thinking_content": null,
"tool_calls": null,
"created_at": "2026-03-24T10:00:01Z"
}
],
"next_cursor": "msg_003",
"has_more": false
}
}
```
#### 发送消息(对话补全)
```
POST /api/conversations/:id/messages
```
**请求体:**
```json
{
"content": "介绍一下你的能力",
"stream": true,
"tools_enabled": true
}
```
| 参数 | 类型 | 说明 |
| --------------- | -------- | ---------------------- |
| `content` | string | 用户消息内容 |
| `stream` | boolean | 是否流式响应,默认 `true` |
| `tools_enabled` | boolean | 是否启用工具调用,默认 `true`(可选) |
**流式响应 (stream=true)**
**普通回复示例:**
```
HTTP/1.1 200 OK
Content-Type: text/event-stream
event: thinking
data: {"content": "用户想了解我的能力..."}
event: message
data: {"content": "我是"}
event: message
data: {"content": "智谱AI"}
event: message
data: {"content": "开发的大语言模型"}
event: done
data: {"message_id": "msg_003", "token_count": 200}
```
**工具调用示例:**
```
HTTP/1.1 200 OK
Content-Type: text/event-stream
event: thinking
data: {"content": "用户想知道北京天气..."}
event: tool_calls
data: {"calls": [{"id": "call_001", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"北京\"}"}}]}
event: tool_result
data: {"name": "get_weather", "content": "{\"temperature\": 25, \"humidity\": 60, \"description\": \"晴天\"}"}
event: message
data: {"content": "北京"}
event: message
data: {"content": "今天天气晴朗,"}
event: message
data: {"content": "温度25°C"}
event: message
data: {"content": "湿度60%"}
event: done
data: {"message_id": "msg_003", "token_count": 150}
```
**非流式响应 (stream=false)**
```json
{
"code": 0,
"data": {
"message": {
"id": "msg_003",
"conversation_id": "conv_abc123",
"role": "assistant",
"content": "我是智谱AI开发的大语言模型...",
"token_count": 200,
"thinking_content": "用户想了解我的能力...",
"tool_calls": null,
"created_at": "2026-03-24T10:01:00Z"
},
"usage": {
"prompt_tokens": 50,
"completion_tokens": 200,
"total_tokens": 250
}
}
}
```
#### 删除消息
```
DELETE /api/conversations/:id/messages/:message_id
```
**响应:**
```json
{
"code": 0,
"message": "deleted"
}
```
---
### 3. 模型与工具
#### 获取模型列表
```
GET /api/models
```
**响应:**
```json
{
"code": 0,
"data": [
{"id": "glm-5", "name": "GLM-5"},
{"id": "glm-5-turbo", "name": "GLM-5 Turbo"},
{"id": "glm-4.5", "name": "GLM-4.5"},
{"id": "glm-4.6", "name": "GLM-4.6"},
{"id": "glm-4.7", "name": "GLM-4.7"}
]
}
```
#### 获取工具列表
```
GET /api/tools
```
**响应:**
```json
{
"code": 0,
"data": {
"tools": [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
],
"total": 1
}
}
```
---
### 4. 统计信息
#### 获取 Token 使用统计
```
GET /api/stats/tokens?period=daily
```
**参数:**
| 参数 | 类型 | 说明 |
| -------- | ------ | ------------------------------------- |
| `period` | string | 统计周期:`daily`(今日)、`weekly`近7天、`monthly`近30天 |
**响应daily**
```json
{
"code": 0,
"data": {
"period": "daily",
"date": "2026-03-24",
"prompt_tokens": 1000,
"completion_tokens": 2000,
"total_tokens": 3000,
"by_model": {
"glm-5": {
"prompt": 500,
"completion": 1000,
"total": 1500
},
"glm-4": {
"prompt": 500,
"completion": 1000,
"total": 1500
}
}
}
}
```
**响应weekly/monthly**
```json
{
"code": 0,
"data": {
"period": "weekly",
"start_date": "2026-03-18",
"end_date": "2026-03-24",
"prompt_tokens": 7000,
"completion_tokens": 14000,
"total_tokens": 21000,
"daily": {
"2026-03-18": {"prompt": 1000, "completion": 2000, "total": 3000},
"2026-03-19": {"prompt": 1000, "completion": 2000, "total": 3000},
...
}
}
}
```
---
### 5. SSE 事件说明
| 事件 | 说明 |
| ------------- | ---------------------------------------- |
| `thinking` | 思维链增量内容(启用时) |
| `message` | 回复内容的增量片段 |
| `tool_calls` | 工具调用信息,包含工具名称和参数 |
| `tool_result` | 工具执行结果,包含工具名称和返回内容 |
| `error` | 错误信息 |
| `done` | 回复结束,携带完整 message_id 和 token 统计 |
**tool_calls 事件数据格式:**
```json
{
"calls": [
{
"id": "call_001",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"北京\"}"
}
}
]
}
```
**tool_result 事件数据格式:**
```json
{
"name": "get_weather",
"content": "{\"temperature\": 25, \"humidity\": 60}"
}
```
---
### 6. 错误码
| code | 说明 |
| ----- | -------- |
| `0` | 成功 |
| `400` | 请求参数错误 |
| `401` | 未认证 |
| `403` | 无权限访问该资源 |
| `404` | 资源不存在 |
| `429` | 请求过于频繁 |
| `500` | 上游模型服务错误 |
| `503` | 服务暂时不可用 |
**错误响应格式:**
```json
{
"code": 404,
"message": "conversation not found"
}
```
---
## 数据模型
### ER 关系
```
User 1 ── * Conversation 1 ── * Message
```
### Conversation会话
| 字段 | 类型 | 说明 |
| ------------------ | ------------- | --------------------- |
| `id` | string (UUID) | 会话 ID |
| `user_id` | string | 所属用户 ID |
| `title` | string | 会话标题 |
| `model` | string | 使用的模型,默认 `glm-5` |
| `system_prompt` | string | 系统提示词 |
| `temperature` | float | 采样温度,默认 `1.0` |
| `max_tokens` | integer | 最大输出 token默认 `65536` |
| `thinking_enabled` | boolean | 是否启用思维链,默认 `false` |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |
### Message消息
| 字段 | 类型 | 说明 |
| ------------------ | ------------- | ------------------------------- |
| `id` | string (UUID) | 消息 ID |
| `conversation_id` | string | 所属会话 ID |
| `role` | enum | `user` / `assistant` / `system` |
| `content` | string | 消息内容 |
| `token_count` | integer | token 消耗数 |
| `thinking_content` | string | 思维链内容(启用时) |
| `tool_calls` | array (JSON) | 工具调用信息(含结果),仅 assistant 消息 |
| `created_at` | datetime | 创建时间 |
#### 消息类型说明
**1. 用户消息 (role=user)**
```json
{
"id": "msg_001",
"role": "user",
"content": "北京今天天气怎么样?",
"created_at": "2026-03-24T10:00:00Z"
}
```
**2. 助手消息 - 普通回复 (role=assistant)**
```json
{
"id": "msg_002",
"role": "assistant",
"content": "北京今天天气晴朗...",
"token_count": 50,
"thinking_content": "用户想了解天气...",
"tool_calls": null,
"created_at": "2026-03-24T10:00:01Z"
}
```
**3. 助手消息 - 含工具调用 (role=assistant, with tool_calls)**
工具调用结果直接合并到 `tool_calls` 数组中,每个调用包含 `result` 字段:
```json
{
"id": "msg_003",
"role": "assistant",
"content": "北京今天天气晴朗温度25°C湿度60%",
"token_count": 80,
"thinking_content": "用户想知道北京天气,需要调用工具获取...",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"北京\"}"
},
"result": "{\"temperature\": 25, \"humidity\": 60, \"description\": \"晴天\"}"
}
],
"created_at": "2026-03-24T10:00:02Z"
}
```
#### 工具调用流程示例
```
用户: "北京今天天气怎么样?"
[msg_001] role=user, content="北京今天天气怎么样?"
[AI 调用工具 get_weather]
[msg_002] role=assistant, tool_calls=[{get_weather, args:{"city":"北京"}, result="{...}"}]
content="北京今天天气晴朗温度25°C..."
```
**说明:**
- 工具调用结果直接存储在 `tool_calls[].result` 字段中
- 不再创建独立的 `role=tool` 消息
- 前端可通过 `tool_calls` 数组展示完整的工具调用过程
---
## 前端特性
### 工具调用控制
- 工具调用开关位于输入框右侧(扳手图标)
- 状态存储在浏览器 localStorage`tools_enabled`
- 默认开启,可通过请求参数 `tools_enabled` 控制每次请求
### 消息渲染
- 助手消息的 `tool_calls` 通过可折叠面板展示
- 面板显示:思考过程 → 工具调用 → 工具结果
- 每个子项可独立展开/折叠