docs: update 3 reference docs + add Android design, Feishu bot config, productization plan
- Rewrite api-reference.md: 245 endpoints across 38 modules, correct auth paths and response format - Rewrite 内置工具列表.md: all 56 real tools in 11 categories - Fix quickstart.md: local dev ports (3001/8038) vs Docker (8037/8038), --port 8038 - Add android-app-design.md: Kotlin/Compose/MVVM design with SSE, FCM, voice - Add 飞书智能体配置手册.md: all 6 bots config, capabilities, memory architecture - Add 产品化落地方案.md: PWA/voice/push/Flutter productization roadmap Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
720
docs/android-app-design.md
Normal file
720
docs/android-app-design.md
Normal file
@@ -0,0 +1,720 @@
|
|||||||
|
# Android App 设计文档
|
||||||
|
|
||||||
|
天工智能体平台 Android 客户端,提供 AI 对话、语音交互、推送通知等核心移动端能力。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、技术选型
|
||||||
|
|
||||||
|
| 层面 | 选择 | 理由 |
|
||||||
|
|------|------|------|
|
||||||
|
| 语言 | Kotlin | Android 官方首选,协程天然适配 SSE 流式 |
|
||||||
|
| UI 框架 | Jetpack Compose | 声明式 UI,与消息列表/流式更新天然契合 |
|
||||||
|
| 架构 | MVVM + Repository | ViewModel 管理 UI 状态,Repository 统一数据源 |
|
||||||
|
| 网络 | OkHttp 4 + Retrofit 2 | Retrofit 处理 REST,OkHttp 拦截器处理 JWT/重登录 |
|
||||||
|
| SSE | 自定义 OkHttp EventSource | Retrofit 不原生支持 SSE,需基于 OkHttp 手动解析 |
|
||||||
|
| 本地存储 | Room + DataStore | Room 存消息历史,DataStore 存 Token/偏好 |
|
||||||
|
| 图片加载 | Coil | Kotlin 原生,Compose 集成好 |
|
||||||
|
| 音频录制 | MediaRecorder | 系统原生 API,无额外依赖 |
|
||||||
|
| 音频播放 | Media3 ExoPlayer | Google 官方推荐 |
|
||||||
|
| 推送 | Firebase Cloud Messaging | Google 官方,免费 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
android/
|
||||||
|
├── app/
|
||||||
|
│ ├── build.gradle.kts
|
||||||
|
│ └── src/main/
|
||||||
|
│ ├── AndroidManifest.xml
|
||||||
|
│ ├── java/com/tiangong/aiagent/
|
||||||
|
│ │ ├── TiangongApp.kt # Application 类
|
||||||
|
│ │ ├── MainActivity.kt # 单 Activity 入口
|
||||||
|
│ │ │
|
||||||
|
│ │ ├── data/
|
||||||
|
│ │ │ ├── remote/
|
||||||
|
│ │ │ │ ├── ApiService.kt # Retrofit 接口定义
|
||||||
|
│ │ │ │ ├── SseClient.kt # SSE 流式解析器
|
||||||
|
│ │ │ │ └── AuthInterceptor.kt # JWT 注入 + 401 自动重登录
|
||||||
|
│ │ │ ├── local/
|
||||||
|
│ │ │ │ ├── AppDatabase.kt # Room 数据库
|
||||||
|
│ │ │ │ ├── MessageDao.kt # 消息 DAO
|
||||||
|
│ │ │ │ └── ConversationDao.kt # 会话 DAO
|
||||||
|
│ │ │ └── repository/
|
||||||
|
│ │ │ ├── AuthRepository.kt # 登录/Token 管理
|
||||||
|
│ │ │ ├── ChatRepository.kt # 对话/SSE 流式
|
||||||
|
│ │ │ ├── AgentRepository.kt # Agent 列表/详情
|
||||||
|
│ │ │ └── NotificationRepository.kt # 通知轮询
|
||||||
|
│ │ │
|
||||||
|
│ │ ├── domain/
|
||||||
|
│ │ │ └── model/
|
||||||
|
│ │ │ ├── Agent.kt # 智能体
|
||||||
|
│ │ │ ├── Message.kt # 消息(user/assistant/tool/system)
|
||||||
|
│ │ │ ├── Conversation.kt # 会话
|
||||||
|
│ │ │ ├── SseEvent.kt # SSE 事件密封类
|
||||||
|
│ │ │ ├── TokenUsage.kt # Token 用量
|
||||||
|
│ │ │ └── Notification.kt # 通知
|
||||||
|
│ │ │
|
||||||
|
│ │ ├── ui/
|
||||||
|
│ │ │ ├── navigation/
|
||||||
|
│ │ │ │ └── NavGraph.kt # 路由导航图
|
||||||
|
│ │ │ ├── theme/
|
||||||
|
│ │ │ │ └── Theme.kt # Material3 主题
|
||||||
|
│ │ │ ├── login/
|
||||||
|
│ │ │ │ ├── LoginScreen.kt
|
||||||
|
│ │ │ │ └── LoginViewModel.kt
|
||||||
|
│ │ │ ├── chat/
|
||||||
|
│ │ │ │ ├── ChatScreen.kt # 对话主界面
|
||||||
|
│ │ │ │ ├── ChatViewModel.kt # SSE 流式消费 + 消息管理
|
||||||
|
│ │ │ │ └── components/
|
||||||
|
│ │ │ │ ├── MessageBubble.kt # 气泡(支持 Markdown)
|
||||||
|
│ │ │ │ ├── VoiceInputButton.kt # 语音录制按钮
|
||||||
|
│ │ │ │ ├── ToolCallCard.kt # 工具调用卡片
|
||||||
|
│ │ │ │ └── StreamingText.kt # 打字机流式文本
|
||||||
|
│ │ │ ├── agents/
|
||||||
|
│ │ │ │ ├── AgentListScreen.kt
|
||||||
|
│ │ │ │ └── AgentListViewModel.kt
|
||||||
|
│ │ │ └── settings/
|
||||||
|
│ │ │ └── SettingsScreen.kt
|
||||||
|
│ │ │
|
||||||
|
│ │ ├── util/
|
||||||
|
│ │ │ ├── AudioRecorder.kt # 录音工具(MediaRecorder)
|
||||||
|
│ │ │ ├── AudioPlayer.kt # TTS 播放器(ExoPlayer)
|
||||||
|
│ │ │ ├── MarkdownRenderer.kt # Markdown 渲染
|
||||||
|
│ │ │ └── FcmTokenManager.kt # FCM Token 注册/同步
|
||||||
|
│ │ │
|
||||||
|
│ │ └── di/
|
||||||
|
│ │ └── AppModule.kt # Hilt 依赖注入
|
||||||
|
│ │
|
||||||
|
│ └── res/
|
||||||
|
│ ├── values/strings.xml
|
||||||
|
│ └── drawable/ # 图标资源
|
||||||
|
│
|
||||||
|
├── build.gradle.kts # 根构建文件
|
||||||
|
├── settings.gradle.kts
|
||||||
|
└── gradle.properties
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、网络层设计
|
||||||
|
|
||||||
|
### 3.1 基础配置
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// data/remote/ApiService.kt
|
||||||
|
interface ApiService {
|
||||||
|
|
||||||
|
// --- 认证 ---
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("api/v1/auth/login")
|
||||||
|
suspend fun login(
|
||||||
|
@Field("username") username: String,
|
||||||
|
@Field("password") password: String
|
||||||
|
): LoginResponse
|
||||||
|
|
||||||
|
@GET("api/v1/auth/me")
|
||||||
|
suspend fun getCurrentUser(): UserResponse
|
||||||
|
|
||||||
|
// --- Agent ---
|
||||||
|
@GET("api/v1/agents")
|
||||||
|
suspend fun getAgents(
|
||||||
|
@Query("skip") skip: Int = 0,
|
||||||
|
@Query("limit") limit: Int = 100
|
||||||
|
): Response<List<AgentResponse>> // X-Total-Count 在 header
|
||||||
|
|
||||||
|
@GET("api/v1/agents/{agentId}")
|
||||||
|
suspend fun getAgent(@Path("agentId") agentId: String): AgentResponse
|
||||||
|
|
||||||
|
// --- 对话(非流式) ---
|
||||||
|
@POST("api/v1/agent-chat/{agentId}")
|
||||||
|
suspend fun chat(
|
||||||
|
@Path("agentId") agentId: String,
|
||||||
|
@Body request: ChatRequest
|
||||||
|
): ChatResponse
|
||||||
|
|
||||||
|
// --- 通知 ---
|
||||||
|
@GET("api/v1/notifications/unread-count")
|
||||||
|
suspend fun getUnreadCount(): UnreadCountResponse
|
||||||
|
|
||||||
|
@GET("api/v1/notifications")
|
||||||
|
suspend fun getNotifications(
|
||||||
|
@Query("unread_only") unreadOnly: Boolean = false,
|
||||||
|
@Query("limit") limit: Int = 50,
|
||||||
|
@Query("offset") offset: Int = 0
|
||||||
|
): List<NotificationResponse>
|
||||||
|
|
||||||
|
// --- FCM Token 注册(新增后端接口) ---
|
||||||
|
@POST("api/v1/push/register")
|
||||||
|
suspend fun registerFcmToken(@Body request: FcmRegisterRequest)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 关键接口参数
|
||||||
|
|
||||||
|
**登录(form-encoded)** — 后端使用 OAuth2PasswordRequestForm,不走 JSON:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 请求
|
||||||
|
data class LoginRequest(
|
||||||
|
val username: String, // Field: username
|
||||||
|
val password: String // Field: password
|
||||||
|
)
|
||||||
|
// 响应
|
||||||
|
data class LoginResponse(
|
||||||
|
val access_token: String,
|
||||||
|
val token_type: String // "bearer"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**对话请求/响应**:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
data class ChatRequest(
|
||||||
|
val message: String,
|
||||||
|
@SerializedName("session_id") val sessionId: String? = null,
|
||||||
|
val streamlined: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// 流式 SSE 事件密封类
|
||||||
|
sealed class SseEvent {
|
||||||
|
data class Message(val content: String) : SseEvent()
|
||||||
|
data class ToolCall(val toolName: String, val toolInput: String) : SseEvent()
|
||||||
|
data class ToolResult(val toolName: String, val toolOutput: String, val success: Boolean) : SseEvent()
|
||||||
|
data class Plan(val plan: PlanObject) : SseEvent()
|
||||||
|
data class Done(
|
||||||
|
val sessionId: String,
|
||||||
|
val iterationsUsed: Int,
|
||||||
|
val toolCallsMade: Int,
|
||||||
|
val tokenUsage: TokenUsage
|
||||||
|
) : SseEvent()
|
||||||
|
data class Error(val error: String) : SseEvent()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 SSE 流式解析器
|
||||||
|
|
||||||
|
后端 SSE 格式为 `event: type\ndata: json\n\n`,需手动解析:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// data/remote/SseClient.kt
|
||||||
|
class SseClient(private val okHttpClient: OkHttpClient) {
|
||||||
|
|
||||||
|
fun connect(url: String, token: String, body: ChatRequest): Flow<SseEvent> = callbackFlow {
|
||||||
|
val requestBody = body.toJson().toRequestBody("application/json".toMediaType())
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header("Authorization", "Bearer $token")
|
||||||
|
.header("Accept", "text/event-stream")
|
||||||
|
.post(requestBody)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val call = okHttpClient.newCall(request)
|
||||||
|
val response = call.execute()
|
||||||
|
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
close(IOException("HTTP ${response.code}"))
|
||||||
|
return@callbackFlow
|
||||||
|
}
|
||||||
|
|
||||||
|
val source = response.body?.source() ?: return@callbackFlow
|
||||||
|
var eventType = ""
|
||||||
|
var data = ""
|
||||||
|
|
||||||
|
while (!source.exhausted()) {
|
||||||
|
val line = source.readUtf8Line() ?: break
|
||||||
|
|
||||||
|
when {
|
||||||
|
line.startsWith("event: ") -> eventType = line.removePrefix("event: ")
|
||||||
|
line.startsWith("data: ") -> data = line.removePrefix("data: ")
|
||||||
|
line.isEmpty() -> {
|
||||||
|
// 空行 = 事件结束
|
||||||
|
if (data.isNotEmpty()) {
|
||||||
|
val event = parseEvent(eventType, data)
|
||||||
|
trySend(event)
|
||||||
|
}
|
||||||
|
eventType = ""
|
||||||
|
data = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseEvent(type: String, json: String): SseEvent = when (type) {
|
||||||
|
"message" -> SseEvent.Message(extractContent(json))
|
||||||
|
"tool_call" -> {
|
||||||
|
val obj = JsonParser.parseString(json).asJsonObject
|
||||||
|
SseEvent.ToolCall(
|
||||||
|
obj["tool_name"].asString,
|
||||||
|
obj["tool_input"].asString
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"tool_result" -> {
|
||||||
|
val obj = JsonParser.parseString(json).asJsonObject
|
||||||
|
SseEvent.ToolResult(
|
||||||
|
obj["tool_name"].asString,
|
||||||
|
obj["tool_output"].asString,
|
||||||
|
obj["success"].asBoolean
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"done" -> SseEvent.Done(/* parse full done payload */)
|
||||||
|
"error" -> SseEvent.Error(extractError(json))
|
||||||
|
else -> SseEvent.Message("") // 未知类型忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 JWT 拦截器 + 自动重登录
|
||||||
|
|
||||||
|
Token 30 分钟过期,无 refresh 端点,401 时自动重登录:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// data/remote/AuthInterceptor.kt
|
||||||
|
class AuthInterceptor(
|
||||||
|
private val tokenStore: TokenDataStore, // DataStore 存 token
|
||||||
|
private val credentialStore: CredentialStore // 加密存用户名密码
|
||||||
|
) : Interceptor {
|
||||||
|
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val token = runBlocking { tokenStore.getToken() }
|
||||||
|
|
||||||
|
val request = if (token != null) {
|
||||||
|
chain.request().newBuilder()
|
||||||
|
.header("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
} else {
|
||||||
|
chain.request()
|
||||||
|
}
|
||||||
|
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
|
// 401 自动重登录
|
||||||
|
if (response.code == 401) {
|
||||||
|
response.close()
|
||||||
|
val credentials = runBlocking { credentialStore.getCredentials() }
|
||||||
|
if (credentials != null) {
|
||||||
|
val newToken = runBlocking { reLogin(credentials) }
|
||||||
|
if (newToken != null) {
|
||||||
|
val retryRequest = request.newBuilder()
|
||||||
|
.header("Authorization", "Bearer $newToken")
|
||||||
|
.build()
|
||||||
|
return chain.proceed(retryRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 重登录也失败,跳转登录页(通过 EventBus 或回调通知 UI)
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun reLogin(cred: Credentials): String? {
|
||||||
|
// 使用单独的 OkHttp 客户端(不走本拦截器,避免死循环)
|
||||||
|
val client = OkHttpClient()
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("username", cred.username)
|
||||||
|
.add("password", cred.password)
|
||||||
|
.build()
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("${BuildConfig.BASE_URL}/api/v1/auth/login")
|
||||||
|
.post(body)
|
||||||
|
.build()
|
||||||
|
val response = client.newCall(request).execute()
|
||||||
|
return if (response.isSuccessful) {
|
||||||
|
val json = JsonParser.parseString(response.body?.string()!!).asJsonObject
|
||||||
|
val newToken = json["access_token"].asString
|
||||||
|
tokenStore.saveToken(newToken)
|
||||||
|
newToken
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、屏幕设计
|
||||||
|
|
||||||
|
### 4.1 整体导航
|
||||||
|
|
||||||
|
```
|
||||||
|
MainActivity
|
||||||
|
└── NavHost
|
||||||
|
├── LoginScreen (startDestination)
|
||||||
|
├── ChatScreen (需登录)
|
||||||
|
├── AgentListScreen (需登录,从 Chat 顶部切出)
|
||||||
|
├── SettingsScreen (需登录)
|
||||||
|
└── AboutScreen
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 登录页 — LoginScreen
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 元素 | 用户名输入框、密码输入框、登录按钮、服务器地址(可配置) |
|
||||||
|
| 状态 | 空闲、加载中、错误提示 |
|
||||||
|
| 逻辑 | 登录成功 → 存储 Token + 凭据 → 跳转 ChatScreen |
|
||||||
|
| 安全 | 凭据存 EncryptedSharedPreferences(AndroidX Security) |
|
||||||
|
|
||||||
|
### 4.3 对话页 — ChatScreen
|
||||||
|
|
||||||
|
核心页面,承载主要交互。
|
||||||
|
|
||||||
|
| 区域 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 顶部栏 | 当前 Agent 名称(点击切换)、Agent 在线状态、通知铃铛(红点未读数) |
|
||||||
|
| 消息列表 | LazyColumn 倒序渲染,消息气泡(用户右对齐/助手左对齐),支持 Markdown 渲染 |
|
||||||
|
| 工具调用卡片 | 可折叠卡片,显示工具名/输入/输出,加载状态 |
|
||||||
|
| 流式文本 | 打字机效果,逐 token 显示,光标闪烁 |
|
||||||
|
| 底部输入栏 | 文本输入框 + 语音按钮 + 发送按钮 + 加号(图片/文件) |
|
||||||
|
| 空状态 | 首次进入显示"你好,我是 <Agent名>" + 快捷提问建议 |
|
||||||
|
|
||||||
|
**状态管理(ChatViewModel)**:
|
||||||
|
|
||||||
|
| 事件 | 处理 |
|
||||||
|
|------|------|
|
||||||
|
| 发送消息 | 创建 user Message → 添加到列表 → 创建 assistant 占位 Message → 开启 SSE 连接 |
|
||||||
|
| SSE token | 追加到当前 assistant Message.content |
|
||||||
|
| SSE tool_call | 插入 ToolCallCard(折叠状态) |
|
||||||
|
| SSE tool_result | 更新 ToolCallCard 为展开状态,显示结果 |
|
||||||
|
| SSE done | 停止流式,更新 token_usage,保存消息到 Room |
|
||||||
|
| SSE error | 显示错误提示,消息气泡变红色 |
|
||||||
|
| 切换 Agent | 结束当前 SSE → 清空列表 → 加载新 Agent 信息 |
|
||||||
|
| 退后台/杀进程 | 保存 session_id,下次恢复时带 session_id 继续对话 |
|
||||||
|
|
||||||
|
**消息气泡样式**:
|
||||||
|
|
||||||
|
| 类型 | 对齐 | 样式 |
|
||||||
|
|------|------|------|
|
||||||
|
| user | 右对齐 | 主题色背景,白色字 |
|
||||||
|
| assistant (Markdown) | 左对齐 | 卡片背景,Markdown 渲染正文 |
|
||||||
|
| tool_call | 左对齐 | 缩进卡片,灰色边框,"正在调用 xxx 工具..." |
|
||||||
|
| tool_result | 左对齐 | 缩进卡片,绿色边框(成功)/红色(失败),显示摘要 |
|
||||||
|
| system | 居中 | 灰色小字,如"会话已创建" |
|
||||||
|
|
||||||
|
### 4.4 Agent 列表页 — AgentListScreen
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 触发 | 对话页顶部栏点击 Agent 名称 |
|
||||||
|
| 样式 | BottomSheet 或 全屏页面 |
|
||||||
|
| 列表项 | Agent 头像(首字母)、名称、描述、状态标签(published/stopped) |
|
||||||
|
| 操作 | 点击切换当前对话 Agent,自动创建新 session |
|
||||||
|
| 搜索 | 顶部搜索栏,调用 `GET /agents?search=` |
|
||||||
|
|
||||||
|
### 4.5 设置页 — SettingsScreen
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 服务器地址 | 可编辑,默认 `http://101.43.95.130:8038` |
|
||||||
|
| 语音 | TTS 开关、音色选择(alloy/echo/fable/onyx/nova/shimmer) |
|
||||||
|
| 推送 | 推送开关(注册/注销 FCM Token) |
|
||||||
|
| 主题 | 亮色/暗色/跟随系统 |
|
||||||
|
| 账户 | 当前用户信息、退出登录 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、语音交互
|
||||||
|
|
||||||
|
### 5.1 语音输入(ASR)
|
||||||
|
|
||||||
|
```
|
||||||
|
用户按住语音按钮
|
||||||
|
-> MediaRecorder 录制 AAC/WebM
|
||||||
|
-> 松开按钮,停止录制
|
||||||
|
-> 上传到 POST /api/v1/voice/asr (multipart)
|
||||||
|
-> 返回 { "text": "..." }
|
||||||
|
-> 填入输入框(或直接发送)
|
||||||
|
```
|
||||||
|
|
||||||
|
| 项 | 实现 |
|
||||||
|
|------|------|
|
||||||
|
| 录制 | `MediaRecorder`,输出格式 `AAC_ADTS` 或 `WEBM`(兼容后端 Whisper) |
|
||||||
|
| 采样率 | 16000 Hz(Whisper 推荐) |
|
||||||
|
| 按钮交互 | 按住录音、上滑取消、松开发送(类似微信) |
|
||||||
|
| 振幅动画 | 录音时显示波形动画(`AudioRecord.read()` 获取 PCM 振幅) |
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// util/AudioRecorder.kt
|
||||||
|
class AudioRecorder(private val context: Context) {
|
||||||
|
private var mediaRecorder: MediaRecorder? = null
|
||||||
|
private var outputFile: File? = null
|
||||||
|
|
||||||
|
fun startRecording(): File {
|
||||||
|
outputFile = File(context.cacheDir, "voice_${System.currentTimeMillis()}.aac")
|
||||||
|
mediaRecorder = MediaRecorder(context).apply {
|
||||||
|
setAudioSource(MediaRecorder.AudioSource.MIC)
|
||||||
|
setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS)
|
||||||
|
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
|
||||||
|
setAudioSamplingRate(16000)
|
||||||
|
setOutputFile(outputFile!!.absolutePath)
|
||||||
|
prepare()
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
return outputFile!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopRecording() {
|
||||||
|
mediaRecorder?.apply {
|
||||||
|
stop()
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
mediaRecorder = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 语音输出(TTS)
|
||||||
|
|
||||||
|
```
|
||||||
|
助手回复完成
|
||||||
|
-> 调用 POST /api/v1/voice/tts (JSON: text + voice)
|
||||||
|
-> 返回 { "audio_url": "/api/v1/uploads/tts/xxx.mp3" }
|
||||||
|
-> ExoPlayer 播放
|
||||||
|
-> 消息气泡右下角显示播放按钮
|
||||||
|
```
|
||||||
|
|
||||||
|
| 项 | 实现 |
|
||||||
|
|------|------|
|
||||||
|
| 播放器 | `ExoPlayer` (Media3),支持缓存 |
|
||||||
|
| 触发 | 消息气泡旁播放按钮 / 设置中开启自动朗读 |
|
||||||
|
| 打断 | 用户开始录音时,停止当前 TTS |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、推送通知
|
||||||
|
|
||||||
|
### 6.1 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
后端任务完成/告警
|
||||||
|
-> PushService (新增)
|
||||||
|
-> Firebase Cloud Messaging
|
||||||
|
-> Android 设备
|
||||||
|
-> 通知栏展示
|
||||||
|
-> 点击跳转 App 对应页面
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 客户端实现
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 1. 获取 FCM Token
|
||||||
|
class TiangongApp : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
|
||||||
|
if (task.isSuccessful) {
|
||||||
|
val token = task.result
|
||||||
|
// 同步到后端
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
apiService.registerFcmToken(FcmRegisterRequest(
|
||||||
|
token = token,
|
||||||
|
platform = "android"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 前台消息处理 — 通知弹窗 + 红点更新
|
||||||
|
class TiangongMessagingService : FirebaseMessagingService() {
|
||||||
|
override fun onMessageReceived(message: RemoteMessage) {
|
||||||
|
val title = message.notification?.title ?: message.data["title"] ?: return
|
||||||
|
val body = message.notification?.body ?: message.data["body"] ?: ""
|
||||||
|
val url = message.data["url"] ?: ""
|
||||||
|
|
||||||
|
showNotification(title, body, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNotification(title: String, body: String, deepLink: String) {
|
||||||
|
val channelId = when (message.data["priority"]) {
|
||||||
|
"urgent" -> "agent_urgent"
|
||||||
|
else -> "agent_default"
|
||||||
|
}
|
||||||
|
// 创建通知渠道 + 显示通知
|
||||||
|
// 点击通知 -> deepLink 跳转 (如打开对话页)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 通知渠道
|
||||||
|
|
||||||
|
| 渠道 ID | 名称 | 级别 | 行为 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| agent_reply | AI 回复 | DEFAULT | 声音 + 状态栏 |
|
||||||
|
| agent_urgent | 紧急通知 | HIGH | 声音 + 振动 + 悬浮 |
|
||||||
|
| agent_alert | 系统告警 | MAX | 全屏通知 |
|
||||||
|
|
||||||
|
### 6.4 后端需新增接口
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | `/api/v1/push/register` | 注册 FCM Token(绑定 user_id) |
|
||||||
|
| DELETE | `/api/v1/push/unregister` | 注销 FCM Token |
|
||||||
|
| POST | `/api/v1/push/send` | (内部) 发送推送 — 由 notify_user 工具/告警服务调用 |
|
||||||
|
|
||||||
|
需新增 `push_tokens` 表:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| id | UUID | 主键 |
|
||||||
|
| user_id | UUID | 用户 ID |
|
||||||
|
| token | VARCHAR(512) | FCM token |
|
||||||
|
| platform | VARCHAR(16) | android / ios / web |
|
||||||
|
| created_at | DATETIME | 注册时间 |
|
||||||
|
| last_used_at | DATETIME | 最后一次推送时间 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、数据层
|
||||||
|
|
||||||
|
### 7.1 Room 数据库
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// data/local/AppDatabase.kt
|
||||||
|
@Database(entities = [MessageEntity::class, ConversationEntity::class], version = 1)
|
||||||
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
abstract fun messageDao(): MessageDao
|
||||||
|
abstract fun conversationDao(): ConversationDao
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEntity
|
||||||
|
@Entity(tableName = "messages")
|
||||||
|
data class MessageEntity(
|
||||||
|
@PrimaryKey val id: String, // UUID,客户端生成
|
||||||
|
val conversationId: String, // 会话 ID (即 session_id)
|
||||||
|
val agentId: String?, // 来源 Agent
|
||||||
|
val role: String, // user / assistant / tool / system
|
||||||
|
val content: String, // 正文
|
||||||
|
val toolName: String?, // 工具名(role=tool 时)
|
||||||
|
val toolInput: String?, // 工具输入
|
||||||
|
val toolOutput: String?, // 工具输出
|
||||||
|
val tokenUsage: String?, // JSON 序列化的 TokenUsage
|
||||||
|
val createdAt: Long // 时间戳
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConversationEntity
|
||||||
|
@Entity(tableName = "conversations")
|
||||||
|
data class ConversationEntity(
|
||||||
|
@PrimaryKey val sessionId: String, // = 后端 session_id
|
||||||
|
val agentId: String?,
|
||||||
|
val agentName: String?,
|
||||||
|
val title: String?, // 首条消息截取
|
||||||
|
val lastMessage: String?,
|
||||||
|
val lastMessageAt: Long,
|
||||||
|
val messageCount: Int
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 DataStore
|
||||||
|
|
||||||
|
| 键 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| access_token | String | JWT Token |
|
||||||
|
| server_url | String | 服务器地址 |
|
||||||
|
| current_agent_id | String | 当前选中的 Agent ID |
|
||||||
|
| tts_enabled | Boolean | 是否自动朗读 |
|
||||||
|
| tts_voice | String | 音色选择 |
|
||||||
|
| push_enabled | Boolean | 推送开关 |
|
||||||
|
| theme_mode | String | light / dark / system |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、构建配置
|
||||||
|
|
||||||
|
### 8.1 build.gradle.kts(关键依赖)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// app/build.gradle.kts
|
||||||
|
dependencies {
|
||||||
|
// Compose BOM
|
||||||
|
implementation(platform("androidx.compose:compose-bom:2024.06.00"))
|
||||||
|
implementation("androidx.compose.material3:material3")
|
||||||
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
implementation("androidx.navigation:navigation-compose:2.7.7")
|
||||||
|
|
||||||
|
// Lifecycle + ViewModel
|
||||||
|
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0")
|
||||||
|
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.0")
|
||||||
|
|
||||||
|
// Network
|
||||||
|
implementation("com.squareup.retrofit2:retrofit:2.11.0")
|
||||||
|
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
|
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
|
||||||
|
|
||||||
|
// Room
|
||||||
|
implementation("androidx.room:room-runtime:2.6.1")
|
||||||
|
implementation("androidx.room:room-ktx:2.6.1")
|
||||||
|
kapt("androidx.room:room-compiler:2.6.1")
|
||||||
|
|
||||||
|
// DataStore
|
||||||
|
implementation("androidx.datastore:datastore-preferences:1.1.1")
|
||||||
|
|
||||||
|
// DI
|
||||||
|
implementation("com.google.dagger:hilt-android:2.51")
|
||||||
|
kapt("com.google.dagger:hilt-compiler:2.51")
|
||||||
|
|
||||||
|
// Firebase (推送)
|
||||||
|
implementation(platform("com.google.firebase:firebase-bom:33.1.0"))
|
||||||
|
implementation("com.google.firebase:firebase-messaging-ktx")
|
||||||
|
|
||||||
|
// Media (TTS 播放)
|
||||||
|
implementation("androidx.media3:media3-exoplayer:1.3.1")
|
||||||
|
|
||||||
|
// Markdown 渲染
|
||||||
|
implementation("io.noties.markwon:core:4.6.2")
|
||||||
|
|
||||||
|
// Security (加密凭据)
|
||||||
|
implementation("androidx.security:security-crypto:1.1.0-alpha06")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 最低版本
|
||||||
|
|
||||||
|
| 项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| minSdk | 26 (Android 8.0) |
|
||||||
|
| targetSdk | 34 (Android 14) |
|
||||||
|
| compileSdk | 34 |
|
||||||
|
| Kotlin | 2.0 |
|
||||||
|
| AGP | 8.5 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、工作量估算
|
||||||
|
|
||||||
|
| 模块 | 内容 | 工作量 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 项目搭建 | Gradle 配置、Hilt、主题、导航骨架 | 0.5天 |
|
||||||
|
| 网络层 | Retrofit 接口 + OkHttp 拦截器 + SSE 解析器 | 1天 |
|
||||||
|
| 登录 | 登录页 + ViewModel + Token 持久化 + 自动重登录 | 0.5天 |
|
||||||
|
| 对话页 | ChatScreen + ChatViewModel + SSE 流式消费 + 消息气泡 | 2天 |
|
||||||
|
| Markdown 渲染 | Markwon 集成 + 代码块 + 表格 + 图片 | 0.5天 |
|
||||||
|
| 工具调用 | ToolCallCard + 折叠展开 + 实时更新 | 0.5天 |
|
||||||
|
| Agent 列表 | AgentListScreen + 切换 Agent | 0.5天 |
|
||||||
|
| 语音输入 | AudioRecorder + 语音按钮 + 上传 + ASR 调用 | 1天 |
|
||||||
|
| 语音输出 | ExoPlayer + TTS 调用 + 播放按钮 | 0.5天 |
|
||||||
|
| 推送 | FCM 集成 + 通知渠道 + 后端接口 | 1天 |
|
||||||
|
| 本地存储 | Room 数据库 + DataStore + 消息持久化 | 1天 |
|
||||||
|
| 设置页 | SettingsScreen + 主题切换 | 0.5天 |
|
||||||
|
| 后端推送 | FCM 集成 + push_tokens 表 + 推送 API | 1天 |
|
||||||
|
| 测试联调 | 端到端测试 + 多机型适配 | 2天 |
|
||||||
|
| **合计** | | **12天** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、后端需配合改造
|
||||||
|
|
||||||
|
| 改动 | 说明 | 优先级 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 新增 `/api/v1/voice/asr` | 接收音频文件,返回文本(已有 speech_to_text 工具,封装为 API) | P0 |
|
||||||
|
| 新增 `/api/v1/voice/tts` | 接收文本,返回音频 URL(已有 text_to_speech 工具,封装为 API) | P0 |
|
||||||
|
| 新增 `/api/v1/push/register` | 接收 FCM Token,绑定用户 | P1 |
|
||||||
|
| 新增 `push_tokens` 表 | 存储设备推送 Token | P1 |
|
||||||
|
| FCM Server SDK | 后端集成 `firebase-admin`,从 notify_user 触发推送 | P1 |
|
||||||
|
| Token 过期延长 | 30分钟 → 7天(移动端场景),或增加 refresh_token 机制 | P1 |
|
||||||
@@ -1,403 +1,391 @@
|
|||||||
# 🔌 API 参考文档
|
# API 参考文档
|
||||||
|
|
||||||
> **API Reference**
|
天工智能体平台后端 RESTful API 接口规范。所有 API 前缀为 `/api/v1`。
|
||||||
|
|
||||||
本文档描述了天工智能体平台后端 RESTful API 接口规范。所有 API 均通过 Nginx 反向代理暴露,前缀为 `/api/v1`。
|
启动后端后访问 Swagger UI 可查看完整接口列表并在线调试。
|
||||||
|
|
||||||
> 💡 **交互式文档**:启动后端服务后,可访问 `http://localhost:8037/docs` 查看 Swagger UI 文档。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 一、通用规范
|
## 通用规范
|
||||||
|
|
||||||
### 基础 URL
|
### 基础 URL
|
||||||
|
|
||||||
```
|
| 环境 | 地址 |
|
||||||
生产环境:https://your-domain.com/api/v1
|
|------|------|
|
||||||
开发环境:http://localhost:8037/api/v1
|
| 本地开发 | `http://localhost:8038/api/v1` |
|
||||||
```
|
| Docker 部署 | `http://localhost:8037/api/v1` |
|
||||||
|
| 生产环境 | `https://your-domain.com/api/v1` |
|
||||||
|
|
||||||
### 认证方式
|
### 认证方式
|
||||||
|
|
||||||
所有受保护的接口需在请求头中携带 JWT Token:
|
受保护的接口需在请求头携带 JWT Token:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
Authorization: Bearer <access_token>
|
Authorization: Bearer <access_token>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Token 通过登录接口获取。
|
||||||
|
|
||||||
### 响应格式
|
### 响应格式
|
||||||
|
|
||||||
```json
|
成功响应直接返回 Pydantic 模型序列化 JSON,无外层包装:
|
||||||
// 成功响应
|
|
||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": { ... }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 错误响应
|
```json
|
||||||
{
|
{"access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "bearer"}
|
||||||
"code": 40001,
|
|
||||||
"message": "用户不存在",
|
|
||||||
"data": null
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 通用错误码
|
错误响应:
|
||||||
|
|
||||||
| 状态码 | 错误码 | 说明 |
|
```json
|
||||||
|:------|:-------|:------|
|
{"error": "ERROR_CODE", "message": "human readable message"}
|
||||||
| 200 | 200 | 请求成功 |
|
```
|
||||||
| 400 | 40000 | 请求参数错误 |
|
|
||||||
| 401 | 40100 | 未认证(Token 缺失或过期) |
|
### ID 格式
|
||||||
| 403 | 40300 | 无权限访问 |
|
|
||||||
| 404 | 40400 | 资源不存在 |
|
所有主键(Agent / Workflow / Execution / Goal / Task 等)均为 UUID 字符串(36 字符),不是整数。
|
||||||
| 500 | 50000 | 服务器内部错误 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 二、用户模块
|
## 认证模块 `/api/v1/auth`
|
||||||
|
|
||||||
### 2.1 用户注册
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | `/auth/register` | 用户注册(email + password + nickname) |
|
||||||
|
| POST | `/auth/login` | 登录,返回 access_token |
|
||||||
|
| GET | `/auth/me` | 获取当前用户信息(需 Bearer Token) |
|
||||||
|
|
||||||
注册新用户账号。
|
### 登录
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /api/v1/users/register
|
POST /api/v1/auth/login
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
```
|
```
|
||||||
|
|
||||||
**请求体:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| 参数 | 类型 | 必填 | 说明 |
|
||||||
|:-----|:-----|:-----|:------|
|
|------|------|------|------|
|
||||||
| `email` | string | ✅ | 邮箱地址 |
|
| username | string | 是 | 用户名 |
|
||||||
| `password` | string | ✅ | 密码(至少 8 位,含字母和数字) |
|
| password | string | 是 | 密码 |
|
||||||
| `nickname` | string | ❌ | 用户昵称 |
|
|
||||||
|
|
||||||
**请求示例:**
|
响应:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"email": "user@example.com",
|
|
||||||
"password": "Abc12345",
|
|
||||||
"nickname": "张三"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": {
|
|
||||||
"id": 1,
|
|
||||||
"email": "user@example.com",
|
|
||||||
"nickname": "张三",
|
|
||||||
"created_at": "2026-05-10T08:00:00Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2.2 用户登录
|
|
||||||
|
|
||||||
获取 JWT 访问令牌。
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/v1/users/login
|
|
||||||
```
|
|
||||||
|
|
||||||
**请求体:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `email` | string | ✅ | 邮箱地址 |
|
|
||||||
| `password` | string | ✅ | 密码 |
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": {
|
|
||||||
"access_token": "eyJhbGciOiJIUzI1NiIs...",
|
"access_token": "eyJhbGciOiJIUzI1NiIs...",
|
||||||
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
|
"token_type": "bearer"
|
||||||
"token_type": "bearer",
|
|
||||||
"expires_in": 1800
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.3 Token 刷新
|
## 智能体模块 `/api/v1/agents`
|
||||||
|
|
||||||
使用 Refresh Token 获取新的 Access Token。
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/agents` | 智能体列表(分页、搜索、状态筛选) |
|
||||||
|
| POST | `/agents` | 创建智能体(含 workflow_config) |
|
||||||
|
| GET | `/agents/{agent_id}` | 智能体详情 |
|
||||||
|
| PUT | `/agents/{agent_id}` | 更新智能体(自动递增版本号) |
|
||||||
|
| DELETE | `/agents/{agent_id}` | 删除智能体(所有者或管理员) |
|
||||||
|
| POST | `/agents/{agent_id}/deploy` | 发布智能体 |
|
||||||
|
| POST | `/agents/{agent_id}/stop` | 停止智能体 |
|
||||||
|
| POST | `/agents/{agent_id}/duplicate` | 深拷贝智能体 |
|
||||||
|
| GET | `/agents/{agent_id}/export` | 导出为 JSON |
|
||||||
|
| POST | `/agents/import` | 从 JSON 导入 |
|
||||||
|
| POST | `/agents/{agent_id}/execute` | 执行智能体(agent/sequential/pipeline/debate/graph) |
|
||||||
|
| POST | `/agents/{agent_id}/create-main-agent` | 升级为主 Agent |
|
||||||
|
| GET | `/agents/{agent_id}/preview-chat-history` | 设计预览对话历史 |
|
||||||
|
|
||||||
```http
|
### 创建智能体
|
||||||
POST /api/v1/users/refresh
|
|
||||||
```
|
|
||||||
|
|
||||||
**请求体:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `refresh_token` | string | ✅ | 登录时获取的 Refresh Token |
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": {
|
|
||||||
"access_token": "eyJhbGciOiJIUzI1NiIs...",
|
|
||||||
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
|
|
||||||
"token_type": "bearer",
|
|
||||||
"expires_in": 1800
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2.4 获取当前用户信息
|
|
||||||
|
|
||||||
获取已登录用户的个人信息。
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /api/v1/users/me
|
|
||||||
```
|
|
||||||
|
|
||||||
**请求头:**
|
|
||||||
```http
|
|
||||||
Authorization: Bearer <access_token>
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": {
|
|
||||||
"id": 1,
|
|
||||||
"email": "user@example.com",
|
|
||||||
"nickname": "张三",
|
|
||||||
"avatar": "https://...",
|
|
||||||
"created_at": "2026-05-10T08:00:00Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、智能体模块
|
|
||||||
|
|
||||||
### 3.1 创建智能体
|
|
||||||
|
|
||||||
创建一个新的 AI 智能体。
|
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /api/v1/agents
|
POST /api/v1/agents
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
Content-Type: application/json
|
||||||
```
|
```
|
||||||
|
|
||||||
**请求体:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `name` | string | ✅ | 智能体名称 |
|
|
||||||
| `description` | string | ❌ | 智能体描述 |
|
|
||||||
| `prompt_template` | string | ✅ | 系统提示词模板 |
|
|
||||||
| `model_config` | object | ✅ | LLM 模型配置 |
|
|
||||||
|
|
||||||
**`model_config` 对象:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `provider` | string | ✅ | 模型提供商:`openai` / `azure` / `local` |
|
|
||||||
| `model_name` | string | ✅ | 模型名称:`gpt-4o` / `gpt-3.5-turbo` |
|
|
||||||
| `temperature` | number | ❌ | 生成温度(默认 0.7) |
|
|
||||||
| `max_tokens` | integer | ❌ | 最大 Token 数(默认 2048) |
|
|
||||||
|
|
||||||
**请求示例:**
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "智能客服助手",
|
"name": "智能体名称",
|
||||||
"description": "用于解答常见产品问题",
|
"description": "描述",
|
||||||
"prompt_template": "你是一个专业的客服助手...",
|
"system_prompt": "系统提示词...",
|
||||||
"model_config": {
|
"model_config": {
|
||||||
"provider": "openai",
|
"provider": "openai",
|
||||||
"model_name": "gpt-4o",
|
"model_name": "deepseek-v4-pro",
|
||||||
"temperature": 0.5,
|
"temperature": 0.8
|
||||||
"max_tokens": 2048
|
},
|
||||||
|
"iteration_limit": 15,
|
||||||
|
"include_tools": [],
|
||||||
|
"workflow_config": {
|
||||||
|
"nodes": [
|
||||||
|
{"id": "start", "type": "start", "label": "开始"},
|
||||||
|
{"id": "agent", "type": "agent", "label": "智能体"},
|
||||||
|
{"id": "end", "type": "end", "label": "结束"}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{"source": "start", "target": "agent"},
|
||||||
|
{"source": "agent", "target": "end"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.2 获取智能体列表
|
## 智能体对话 `/api/v1/agent-chat`
|
||||||
|
|
||||||
获取当前用户的所有智能体。
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | `/agent-chat/{agent_id}` | 与指定智能体对话 |
|
||||||
|
| POST | `/agent-chat/{agent_id}/stream` | 流式对话(SSE) |
|
||||||
|
| POST | `/agent-chat/bare` | 默认对话(无需 Agent 配置) |
|
||||||
|
| POST | `/agent-chat/bare/stream` | 默认流式对话(SSE) |
|
||||||
|
| POST | `/agent-chat/orchestrate` | 多 Agent 编排(route/sequential/debate) |
|
||||||
|
| POST | `/agent-chat/orchestrate/graph` | 图模式多 Agent 编排 |
|
||||||
|
|
||||||
|
### 对话请求
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /api/v1/agents?page=1&page_size=20
|
POST /api/v1/agent-chat/{agent_id}
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
Content-Type: application/json
|
||||||
```
|
```
|
||||||
|
|
||||||
**查询参数:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:-------|:------|
|
|
||||||
| `page` | integer | ❌ | 1 | 页码 |
|
|
||||||
| `page_size` | integer | ❌ | 20 | 每页条数(最大 100) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3.3 获取智能体详情
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /api/v1/agents/{agent_id}
|
|
||||||
```
|
|
||||||
|
|
||||||
**路径参数:**
|
|
||||||
|
|
||||||
| 参数 | 类型 | 说明 |
|
|
||||||
|:-----|:-----|:------|
|
|
||||||
| `agent_id` | integer | 智能体 ID |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3.4 更新智能体
|
|
||||||
|
|
||||||
```http
|
|
||||||
PUT /api/v1/agents/{agent_id}
|
|
||||||
```
|
|
||||||
|
|
||||||
**请求体:**(部分更新)
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| 参数 | 类型 | 必填 | 说明 |
|
||||||
|:-----|:-----|:-----|:------|
|
|------|------|------|------|
|
||||||
| `name` | string | ❌ | 智能体名称 |
|
| message | string | 是 | 用户消息 |
|
||||||
| `description` | string | ❌ | 智能体描述 |
|
| session_id | string | 否 | 会话 ID,用于恢复上下文 |
|
||||||
| `prompt_template` | string | ❌ | 系统提示词 |
|
| streamlined | boolean | 否 | 是否精简输出 |
|
||||||
| `model_config` | object | ❌ | 模型配置 |
|
|
||||||
|
### 流式对话 SSE 事件
|
||||||
|
|
||||||
|
| 事件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| token | 输出 token 增量 |
|
||||||
|
| tool_call | 工具调用开始 |
|
||||||
|
| tool_result | 工具返回结果 |
|
||||||
|
| done | 对话完成(含 token_usage) |
|
||||||
|
| error | 错误信息 |
|
||||||
|
|
||||||
|
### 对话分支
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | `/agent-chat/branches` | 创建分支 |
|
||||||
|
| GET | `/agent-chat/branches` | 列出分支 |
|
||||||
|
| GET | `/agent-chat/branches/{branch_id}` | 分支详情 |
|
||||||
|
| DELETE | `/agent-chat/branches/{branch_id}` | 删除分支 |
|
||||||
|
| POST | `/agent-chat/branches/{branch_id}/resume` | 从分支恢复 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.5 删除智能体
|
## 工作流模块 `/api/v1/workflows`
|
||||||
|
|
||||||
```http
|
| 方法 | 路径 | 说明 |
|
||||||
DELETE /api/v1/agents/{agent_id}
|
|------|------|------|
|
||||||
```
|
| GET | `/workflows` | 工作流列表 |
|
||||||
|
| POST | `/workflows` | 创建工作流 |
|
||||||
|
| GET | `/workflows/{workflow_id}` | 工作流详情 |
|
||||||
|
| PUT | `/workflows/{workflow_id}` | 更新工作流 |
|
||||||
|
| DELETE | `/workflows/{workflow_id}` | 删除工作流 |
|
||||||
|
| POST | `/workflows/{workflow_id}/execute` | 执行工作流 |
|
||||||
|
| POST | `/workflows/validate` | 验证工作流配置 |
|
||||||
|
| GET | `/workflows/{workflow_id}/export` | 导出 JSON |
|
||||||
|
| POST | `/workflows/import` | 导入 JSON |
|
||||||
|
| GET | `/workflows/{workflow_id}/versions` | 版本历史 |
|
||||||
|
| GET | `/workflows/{workflow_id}/versions/{v}` | 特定版本详情 |
|
||||||
|
| POST | `/workflows/{workflow_id}/versions/{v}/rollback` | 回滚到指定版本 |
|
||||||
|
|
||||||
|
### 工作流模板
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/workflows/templates` | 模板列表 |
|
||||||
|
| GET | `/workflows/templates/{id}` | 模板详情 |
|
||||||
|
| POST | `/workflows/templates/{id}/create` | 从模板创建 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 四、对话模块
|
## 知识库模块 `/api/v1/knowledge-bases`
|
||||||
|
|
||||||
### 4.1 创建对话会话
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
```http
|
| GET | `/knowledge-bases` | 知识库列表 |
|
||||||
POST /api/v1/conversations
|
| POST | `/knowledge-bases` | 创建知识库 |
|
||||||
```
|
| GET | `/knowledge-bases/{kb_id}` | 知识库详情 |
|
||||||
|
| DELETE | `/knowledge-bases/{kb_id}` | 删除知识库 |
|
||||||
**请求体:**
|
| GET | `/knowledge-bases/{kb_id}/documents` | 文档列表 |
|
||||||
|
| POST | `/knowledge-bases/{kb_id}/documents` | 添加文档 |
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| DELETE | `/knowledge-bases/{kb_id}/documents/{doc_id}` | 删除文档 |
|
||||||
|:-----|:-----|:-----|:------|
|
| POST | `/knowledge-bases/{kb_id}/search` | 语义搜索 |
|
||||||
| `agent_id` | integer | ✅ | 关联的智能体 ID |
|
| POST | `/knowledge-bases/{kb_id}/rag` | RAG 检索增强生成 |
|
||||||
| `title` | string | ❌ | 会话标题(可选) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 发送消息
|
## 工具模块 `/api/v1/tools`
|
||||||
|
|
||||||
向指定对话发送消息,支持流式响应(SSE)。
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
```http
|
| GET | `/tools` | 工具列表 |
|
||||||
POST /api/v1/conversations/{conversation_id}/messages
|
| GET | `/tools/categories` | 工具分类 |
|
||||||
```
|
| GET | `/tools/builtin` | 内置工具列表(56个) |
|
||||||
|
| GET | `/tools/{tool_id}` | 工具详情 |
|
||||||
**请求体:**
|
| POST | `/tools` | 创建自定义工具 |
|
||||||
|
| PUT | `/tools/{tool_id}` | 更新自定义工具 |
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| DELETE | `/tools/{tool_id}` | 删除自定义工具 |
|
||||||
|:-----|:-----|:-----|:------|
|
| POST | `/tools/test/http` | 测试 HTTP 工具 |
|
||||||
| `content` | string | ✅ | 用户消息内容 |
|
| POST | `/tools/test/code` | 测试代码工具 |
|
||||||
|
| POST | `/tools/{tool_id}/use` | 调用工具 |
|
||||||
**流式响应(SSE):**
|
|
||||||
|
|
||||||
```
|
|
||||||
data: {"type": "token", "content": "你好"}
|
|
||||||
data: {"type": "token", "content": ","}
|
|
||||||
data: {"type": "token", "content": "请问有什么可以帮您?"}
|
|
||||||
data: {"type": "done"}
|
|
||||||
data: {"type": "error", "content": "..."}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.3 获取对话历史
|
## 目标与任务
|
||||||
|
|
||||||
```http
|
### 目标 `/api/v1/goals`
|
||||||
GET /api/v1/conversations/{conversation_id}/messages?page=1&page_size=50
|
|
||||||
```
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/goals` | 目标列表 |
|
||||||
|
| POST | `/goals` | 创建目标 |
|
||||||
|
| GET | `/goals/{goal_id}` | 目标详情 |
|
||||||
|
| PUT | `/goals/{goal_id}` | 更新目标 |
|
||||||
|
| DELETE | `/goals/{goal_id}` | 删除目标 |
|
||||||
|
| POST | `/goals/{goal_id}/start` | 启动 |
|
||||||
|
| POST | `/goals/{goal_id}/pause` | 暂停 |
|
||||||
|
| POST | `/goals/{goal_id}/resume` | 恢复 |
|
||||||
|
| POST | `/goals/{goal_id}/decompose` | 分解为任务 |
|
||||||
|
| POST | `/goals/{goal_id}/replan` | 重新规划 |
|
||||||
|
| POST | `/goals/{goal_id}/execute-async` | 异步执行 |
|
||||||
|
| POST | `/goals/{goal_id}/interact` | 对话交互 |
|
||||||
|
| GET | `/goals/{goal_id}/tasks` | 任务树 |
|
||||||
|
|
||||||
|
### 任务 `/api/v1/tasks`
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/tasks` | 任务列表 |
|
||||||
|
| POST | `/tasks` | 创建任务 |
|
||||||
|
| GET | `/tasks/{task_id}` | 任务详情 |
|
||||||
|
| PUT | `/tasks/{task_id}` | 更新任务 |
|
||||||
|
| DELETE | `/tasks/{task_id}` | 删除任务 |
|
||||||
|
| POST | `/tasks/{task_id}/execute` | 执行 |
|
||||||
|
| POST | `/tasks/{task_id}/retry` | 重试 |
|
||||||
|
| POST | `/tasks/{task_id}/claim` | 认领 |
|
||||||
|
| POST | `/tasks/{task_id}/release` | 释放 |
|
||||||
|
| POST | `/tasks/{task_id}/complete` | 完成 |
|
||||||
|
| POST | `/tasks/{task_id}/fail` | 标记失败 |
|
||||||
|
| POST | `/tasks/{task_id}/approve` | 审批通过 |
|
||||||
|
| POST | `/tasks/{task_id}/reject` | 审批拒绝 |
|
||||||
|
| GET | `/tasks/{task_id}/blockers` | 阻塞项 |
|
||||||
|
| GET | `/tasks/available/{goal_id}` | 可接任务 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 五、知识库模块
|
## 智能体蜂群 `/api/v1/swarm`
|
||||||
|
|
||||||
### 5.1 上传文档
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
```http
|
| POST | `/swarm/run` | 运行 Agent 蜂群 |
|
||||||
POST /api/v1/knowledge/documents/upload
|
| POST | `/swarm/run/stream` | 流式运行(SSE) |
|
||||||
```
|
|
||||||
|
|
||||||
**请求格式:** `multipart/form-data`
|
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `file` | file | ✅ | 支持 PDF / TXT / Markdown |
|
|
||||||
| `agent_id` | integer | ✅ | 关联的智能体 ID |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 文档检索
|
## 通知模块 `/api/v1/notifications`
|
||||||
|
|
||||||
```http
|
| 方法 | 路径 | 说明 |
|
||||||
POST /api/v1/knowledge/search
|
|------|------|------|
|
||||||
```
|
| GET | `/notifications` | 通知列表 |
|
||||||
|
| GET | `/notifications/unread-count` | 未读数量 |
|
||||||
**请求体:**
|
| PUT | `/notifications/{id}/read` | 标记已读 |
|
||||||
|
| PUT | `/notifications/read-all` | 全部已读 |
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| DELETE | `/notifications/{id}` | 删除通知 |
|
||||||
|:-----|:-----|:-----|:------|
|
|
||||||
| `query` | string | ✅ | 检索关键词 |
|
|
||||||
| `agent_id` | integer | ✅ | 限定知识库范围 |
|
|
||||||
| `top_k` | integer | ❌ | 返回条数(默认 5) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 六、健康检查
|
## 飞书集成 `/api/v1/feishu`
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| POST | `/feishu/event` | 飞书事件回调 |
|
||||||
|
| POST | `/feishu/bind` | 绑定飞书用户 |
|
||||||
|
| POST | `/feishu/unbind` | 解绑 |
|
||||||
|
| POST | `/feishu/lookup` | 按 open_id 查找 |
|
||||||
|
| GET | `/feishu/status` | 集成状态 |
|
||||||
|
| GET | `/feishu/pending` | 待审批绑定 |
|
||||||
|
| POST | `/feishu/bind-pending` | 审批绑定 |
|
||||||
|
| GET | `/feishu/default-agent` | 默认 Agent |
|
||||||
|
| POST | `/feishu/default-agent` | 设置默认 Agent |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 监控模块
|
||||||
|
|
||||||
|
### 系统监控 `/api/v1/monitoring`
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/monitoring/overview` | 系统概览 |
|
||||||
|
| GET | `/monitoring/executions` | 执行统计 |
|
||||||
|
| GET | `/monitoring/node-types` | 节点类型用量 |
|
||||||
|
| GET | `/monitoring/activities` | 最近动态 |
|
||||||
|
|
||||||
|
### Agent 监控 `/api/v1/agent-monitoring`
|
||||||
|
|
||||||
|
| 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| GET | `/agent-monitoring/overview` | Agent 监控概览 |
|
||||||
|
| GET | `/agent-monitoring/llm-calls` | LLM 调用统计 |
|
||||||
|
| GET | `/agent-monitoring/agents-stats` | Agent 统计 |
|
||||||
|
| GET | `/agent-monitoring/tool-usage` | 工具用量 |
|
||||||
|
| GET | `/agent-monitoring/daily-trend` | 每日趋势 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 其他模块速查
|
||||||
|
|
||||||
|
| 模块 | 前缀 | 端点数 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| 执行管理 | `/executions` | 5 | 执行创建/状态/暂停恢复 |
|
||||||
|
| 执行日志 | `/execution-logs` | 8 | 日志查看/性能分析/调用链 |
|
||||||
|
| 数据源 | `/data-sources` | 7 | MySQL/PG/Mongo/Redis/CSV/JSON/API/S3 |
|
||||||
|
| 模型配置 | `/model-configs` | 6 | LLM 模型配置/测试 |
|
||||||
|
| 协作 | `/collaboration` | 2 | WebSocket 协作 + 用户列表 |
|
||||||
|
| 权限管理 | `/permissions` | 14 | 角色/权限/用户-资源分配 |
|
||||||
|
| 告警规则 | `/alert-rules` | 8 | 告警 CRUD/日志/确认 |
|
||||||
|
| Agent 市场 | `/agent-market` | 14 | 发布/安装/评分/收藏/升级 |
|
||||||
|
| 模板市场 | `/template-market` | 11 | 模板发布/安装/评分/收藏 |
|
||||||
|
| 插件 | `/plugins` | 10 | 插件 CRUD/市场/安装/开关 |
|
||||||
|
| 编排模板 | `/orchestration-templates` | 5 | 多 Agent 编排模板 CRUD |
|
||||||
|
| 平台模板 | `/platform` | 4 | 场景模板/快捷创建 |
|
||||||
|
| 节点模板 | `/node-templates` | 6 | 节点配置模板 CRUD |
|
||||||
|
| 节点测试 | `/nodes` | 1 | 单节点调试 |
|
||||||
|
| 审批 | `/approval` | 2 | 审批查询/决议 |
|
||||||
|
| 定时任务 | `/agent-schedules` | 5 | Cron 定时任务/手动触发 |
|
||||||
|
| Webhook | `/webhooks` | 2 | 按 ID/名称触发工作流 |
|
||||||
|
| 批量操作 | `/batch` | 3 | 批量执行/导出/删除 |
|
||||||
|
| 文件上传 | `/uploads` | 2 | 工作区文件上传/预览 |
|
||||||
|
| 系统日志 | `/system-logs` | 3 | 统一日志/统计/应用日志 |
|
||||||
|
| 审计日志 | `/audit-logs` | 2 | 操作审计日志/统计 |
|
||||||
|
| 反馈 | `/feedback` | 3 | 用户反馈分析/记录/负样本 |
|
||||||
|
| WebSocket | `/ws/executions/{id}` | 1 | 执行状态实时推送 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 健康检查
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /api/v1/health
|
GET /health
|
||||||
```
|
```
|
||||||
|
|
||||||
**响应:**
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"timestamp": "2026-05-10T08:00:00Z"
|
"builtin_tools": {"count": 56, "ready": true}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
> 📎 **相关文档**:[快速开始指南](./quickstart.md) | [开发指南](./development-guide.md)
|
> 完整接口文档:启动后端后访问 Swagger UI(本地 `http://localhost:8038/docs`,Docker `http://localhost:8037/docs`),包含全部 245 个端点的详细参数和在线调试功能。
|
||||||
|
|
||||||
|
> 快速验证命令参考 [平台资料](../平台资料.md)
|
||||||
|
|||||||
@@ -1,287 +1,159 @@
|
|||||||
# 内置工具列表
|
# 内置工具列表
|
||||||
|
|
||||||
平台目前提供 **8个内置工具**,可以在LLM节点中启用工具调用来使用。
|
平台提供 56 个内置工具,覆盖 11 个功能类别。工具定义在 `backend/app/services/builtin_tools.py`,启动时通过 ToolRegistry 自动注册。
|
||||||
|
|
||||||
## 📋 工具列表
|
可在工作流 LLM 节点中启用工具调用,Agent 会自动选择合适的工具执行任务。
|
||||||
|
|
||||||
### 1. 🌐 http_request - HTTP请求工具
|
|
||||||
|
|
||||||
**功能**: 发送HTTP请求,支持GET、POST、PUT、DELETE方法
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 调用外部API
|
|
||||||
- 获取网页内容
|
|
||||||
- 发送数据到服务器
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `url` (必需): 请求的URL地址
|
|
||||||
- `method` (可选): HTTP方法,默认GET
|
|
||||||
- `headers` (可选): HTTP请求头
|
|
||||||
- `body` (可选): 请求体(POST/PUT时使用)
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"url": "https://api.github.com/users/octocat",
|
|
||||||
"method": "GET"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2. 📖 file_read - 文件读取工具
|
## 文件操作(2个)
|
||||||
|
|
||||||
**功能**: 读取文件内容
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| file_read | 读取文件 | 支持 UTF-8 文本、PDF 文字层、DOCX 段落、XLSX 单元格、图片 OCR。路径限制在 LOCAL_FILE_TOOLS_ROOT |
|
||||||
|
| file_write | 写入文件 | UTF-8 文本写入,支持覆盖/追加模式,自动创建父目录 |
|
||||||
|
|
||||||
**用途**:
|
## 网络请求(5个)
|
||||||
- 读取配置文件
|
|
||||||
- 读取文档内容
|
|
||||||
- 读取数据文件
|
|
||||||
|
|
||||||
**参数**:
|
| 工具 | 功能 | 说明 |
|
||||||
- `file_path` (必需): 文件路径(只能读取项目目录下的文件)
|
|------|------|------|
|
||||||
|
| http_request | HTTP 请求 | GET/POST/PUT/DELETE,支持自定义 headers 和 body |
|
||||||
|
| url_parse | URL 解析 | 解析 URL 结构、提取查询参数、构建带参数 URL |
|
||||||
|
| web_search | 网页搜索 | Bing(主)/ DuckDuckGo(备用),返回标题、摘要、URL |
|
||||||
|
| send_email | 邮件发送 | SMTP 发送,配置从环境变量读取 |
|
||||||
|
| browser_use | 浏览器控制 | 无头浏览器:截图、提取内容、点击、填表、执行 JS。需要 playwright |
|
||||||
|
|
||||||
**示例**:
|
## 数据处理(7个)
|
||||||
```json
|
|
||||||
{
|
| 工具 | 功能 | 说明 |
|
||||||
"file_path": "backend/app/core/config.py"
|
|------|------|------|
|
||||||
}
|
| text_analyze | 文本分析 | 统计字数/行数/段落、提取关键词、生成摘要 |
|
||||||
```
|
| json_process | JSON 处理 | 解析(parse)、序列化(stringify)、验证(validate) |
|
||||||
|
| math_calculate | 数学计算 | 基本运算 + sqrt/sin/cos/log/pow 等函数,使用安全 eval |
|
||||||
|
| regex_test | 正则测试 | match/findall/replace/split/validate,支持 i/m/s 标志 |
|
||||||
|
| random_generate | 随机生成 | 密码、随机字符串、整数、浮点数,使用 secrets 模块 |
|
||||||
|
| crypto_util | 加密哈希 | UUID 生成、Base64 编解码、MD5/SHA256 哈希 |
|
||||||
|
| excel_process | Excel 处理 | 读写数据、添加图表(柱状/折线/饼图)。需要 openpyxl |
|
||||||
|
|
||||||
|
## 数据库(1个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| database_query | 数据库查询 | SELECT 只读查询,支持默认数据库或已配置数据源。不允许 INSERT/UPDATE/DELETE |
|
||||||
|
|
||||||
|
## 系统工具(6个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| system_info | 系统信息 | 操作系统、Python 版本、工作区根目录路径 |
|
||||||
|
| datetime | 日期时间 | 获取当前时间、格式化时间戳 |
|
||||||
|
| adb_log | ADB 日志 | Android logcat、devices 列表、shell 命令,可按 tag/level 过滤 |
|
||||||
|
| git_operation | Git 操作 | 只读:log/diff/status/blame/branch/show/tag/remote |
|
||||||
|
| docker_manage | Docker 管理 | 只读:容器/镜像列表、日志、资源使用、详情检查 |
|
||||||
|
| deploy_push | 部署推送 | 本地文件复制(支持排除规则)或 rsync 远程同步 |
|
||||||
|
|
||||||
|
## AI Agent 扩展(13个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| agent_call | 调用子 Agent | 调用其他已注册 Agent 处理子任务,模糊名称匹配 |
|
||||||
|
| agent_create | 创建子 Agent | 动态创建专业化子 Agent,定义名称/system_prompt/模型/温度,持久化到 DB |
|
||||||
|
| tool_register | 注册工具 | 动态注册 HTTP 工具,URL 模板支持 {param} 占位符,持久化到 DB |
|
||||||
|
| capability_check | 能力自检 | 分析当前工具/子 Agent 能否处理指定任务,返回差距分析 |
|
||||||
|
| code_tool_create | 创建代码工具 | 将 code_execute 验证过的代码持久化为可复用工具 |
|
||||||
|
| extension_log | 扩展日志 | 记录和查询自主扩展历史(子 Agent/工具/代码工具),支持 list/log/evaluate |
|
||||||
|
| self_review | 输出自审 | LLM 输出质量自检,评分 >=0.6 通过 |
|
||||||
|
| task_plan | 任务规划 | 复杂任务分解、进度管理、步骤状态更新 |
|
||||||
|
| project_scaffold | 项目脚手架 | 按模板生成项目目录:fastapi/vue/react/python_cli/shell |
|
||||||
|
| code_execute | 代码执行 | 沙箱执行 Python/JavaScript,返回 stdout/stderr,默认 30s 超时 |
|
||||||
|
| schedule_create | 创建定时任务 | 为 Agent 创建 cron 定时任务(5 字段表达式) |
|
||||||
|
| schedule_list | 列出定时任务 | 列出指定 Agent 的所有定时任务 |
|
||||||
|
| schedule_delete | 删除定时任务 | 按 schedule_id 或 agent_id 删除 |
|
||||||
|
|
||||||
|
## 知识图谱(4个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| knowledge_graph_search | 图谱搜索 | 向量语义搜索 + 图邻居扩展混合检索 |
|
||||||
|
| knowledge_graph_add | 添加实体 | 从文本提取知识实体和关系,持久化到知识图谱 |
|
||||||
|
| entity_search | 实体搜索 | 关键词搜索实体,按类型过滤(concept/formula/fact/term/task/skill) |
|
||||||
|
| learning_path | 学习路径 | 基于知识图谱推荐学习路径,分析前置依赖 |
|
||||||
|
|
||||||
|
## 多模态(5个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| image_ocr | 图片 OCR | 文字识别(PNG/JPG/WebP/BMP/TIFF)。需要 Tesseract + chi_sim 中文包 |
|
||||||
|
| image_vision | 视觉理解 | 多模态模型分析(物体/场景/文字/图表/表情)。需要 OPENAI_API_KEY |
|
||||||
|
| speech_to_text | 语音转文字 | 音频转文字(mp3/wav/webm/m4a/ogg),使用 OpenAI Whisper。需要 OPENAI_API_KEY |
|
||||||
|
| text_to_speech | 文字转语音 | 文字转 MP3,6 种音色(alloy/echo/fable/onyx/nova/shimmer)。需要 OPENAI_API_KEY |
|
||||||
|
| pdf_generate | PDF 生成 | Markdown 转 PDF(weasyprint),降级为 HTML |
|
||||||
|
|
||||||
|
## 主 Agent 任务管理(4个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| create_task | 创建子任务 | 在目标下创建子任务:标题/描述/优先级/依赖/指派 Agent |
|
||||||
|
| assign_task | 分配任务 | 将任务分配给指定 Agent(仅已发布的 Agent 可被分配) |
|
||||||
|
| check_progress | 查看进度 | 目标下所有任务进度:状态统计 + 逐任务详情 |
|
||||||
|
| notify_user | 通知用户 | 站内通知(info/success/warning/error),支持 Markdown |
|
||||||
|
|
||||||
|
## 飞书集成(7个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| feishu_create_doc | 创建飞书文档 | 创建飞书在线文档。需要 FEISHU_APP_ID/FEISHU_APP_SECRET |
|
||||||
|
| feishu_create_calendar_event | 创建飞书日历 | 创建日历事件(会议/提醒/截止日),ISO 时间格式 |
|
||||||
|
| feishu_search_contacts | 搜索通讯录 | 按姓名/邮箱/部门搜索飞书通讯录 |
|
||||||
|
| feishu_send_approval | 飞书审批 | 发送审批卡片消息,审批人可直接同意/拒绝 |
|
||||||
|
| feishu_read_messages | 读取消息 | 读取飞书历史消息(P2P 私聊或群聊) |
|
||||||
|
| feishu_create_sheet | 创建飞书表格 | 创建电子表格,用于报告/任务追踪 |
|
||||||
|
| feishu_upload_file | 上传文件 | 上传文件到飞书,返回 file_key 用于消息引用 |
|
||||||
|
|
||||||
|
## DevOps / 测试(2个)
|
||||||
|
|
||||||
|
| 工具 | 功能 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| create_gitea_issue | 创建 Issue | 在 Gitea 中创建 Issue,用于 bug 跟踪/任务登记 |
|
||||||
|
| parse_test_result_file | 解析测试结果 | 解析 JSON/XML/CSV 测试结果,提取 pass/fail/skip 统计。支持 JUnit XML、TestNG XML、pytest JSON |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3. ✍️ file_write - 文件写入工具
|
## 工具调用流程
|
||||||
|
|
||||||
**功能**: 写入文件内容
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 保存处理结果
|
|
||||||
- 创建配置文件
|
|
||||||
- 写入日志文件
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `file_path` (必需): 文件路径(只能写入项目目录下的文件)
|
|
||||||
- `content` (必需): 要写入的内容
|
|
||||||
- `mode` (可选): 写入模式(w=覆盖,a=追加),默认w
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"file_path": "output/result.txt",
|
|
||||||
"content": "处理结果",
|
|
||||||
"mode": "w"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 📊 text_analyze - 文本分析工具
|
|
||||||
|
|
||||||
**功能**: 分析文本内容
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 统计文本字数、行数等
|
|
||||||
- 提取关键词
|
|
||||||
- 生成文本摘要
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `text` (必需): 要分析的文本内容
|
|
||||||
- `operation` (可选): 操作类型
|
|
||||||
- `count`: 统计字数、字符数、行数、段落数
|
|
||||||
- `keywords`: 提取关键词(基于词频)
|
|
||||||
- `summary`: 生成摘要(取前3句)
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"text": "这是一段很长的文本...",
|
|
||||||
"operation": "count"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 🕐 datetime - 日期时间工具
|
|
||||||
|
|
||||||
**功能**: 获取和处理日期时间信息
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 获取当前时间
|
|
||||||
- 格式化时间
|
|
||||||
- 时间戳转换
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `operation` (可选): 操作类型
|
|
||||||
- `now`: 获取当前时间(默认)
|
|
||||||
- `format`: 格式化时间
|
|
||||||
- `format` (可选): 时间格式字符串,默认 "%Y-%m-%d %H:%M:%S"
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"operation": "now",
|
|
||||||
"format": "%Y-%m-%d %H:%M:%S"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. 🔢 math_calculate - 数学计算工具
|
|
||||||
|
|
||||||
**功能**: 执行数学计算
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 基本数学运算(加减乘除)
|
|
||||||
- 数学函数计算(sqrt, sin, cos, log等)
|
|
||||||
- 复杂数学表达式计算
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `expression` (必需): 数学表达式
|
|
||||||
|
|
||||||
**支持的函数**:
|
|
||||||
- `sqrt(x)`: 平方根
|
|
||||||
- `sin(x)`, `cos(x)`, `tan(x)`: 三角函数
|
|
||||||
- `log(x)`: 自然对数
|
|
||||||
- `exp(x)`: 指数函数
|
|
||||||
- `abs(x)`: 绝对值
|
|
||||||
- `pow(x, y)`: 幂运算
|
|
||||||
- `pi`: 圆周率
|
|
||||||
- `e`: 自然常数
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"expression": "sqrt(16) + sin(0) * cos(0)"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 7. 💻 system_info - 系统信息工具
|
|
||||||
|
|
||||||
**功能**: 获取系统信息
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 查看操作系统信息
|
|
||||||
- 查看Python版本
|
|
||||||
- 查看系统架构
|
|
||||||
|
|
||||||
**参数**: 无
|
|
||||||
|
|
||||||
**返回信息**:
|
|
||||||
- 操作系统平台
|
|
||||||
- 系统版本
|
|
||||||
- 处理器架构
|
|
||||||
- Python版本
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 8. 📦 json_process - JSON处理工具
|
|
||||||
|
|
||||||
**功能**: 处理JSON数据
|
|
||||||
|
|
||||||
**用途**:
|
|
||||||
- 解析JSON字符串
|
|
||||||
- 序列化数据为JSON
|
|
||||||
- 验证JSON格式
|
|
||||||
|
|
||||||
**参数**:
|
|
||||||
- `json_string` (必需): JSON字符串
|
|
||||||
- `operation` (可选): 操作类型
|
|
||||||
- `parse`: 解析JSON(默认)
|
|
||||||
- `stringify`: 序列化为JSON
|
|
||||||
- `validate`: 验证JSON格式
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"json_string": "{\"name\": \"test\"}",
|
|
||||||
"operation": "parse"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 使用场景示例
|
|
||||||
|
|
||||||
### 场景1: 数据获取和处理
|
|
||||||
```
|
|
||||||
用户: "查询GitHub用户信息并保存到文件"
|
|
||||||
→ LLM调用 http_request 获取数据
|
|
||||||
→ LLM调用 json_process 解析数据
|
|
||||||
→ LLM调用 file_write 保存结果
|
|
||||||
```
|
|
||||||
|
|
||||||
### 场景2: 文本分析
|
|
||||||
```
|
|
||||||
用户: "分析这段文本的字数和关键词"
|
|
||||||
→ LLM调用 text_analyze (count) 统计字数
|
|
||||||
→ LLM调用 text_analyze (keywords) 提取关键词
|
|
||||||
```
|
|
||||||
|
|
||||||
### 场景3: 数学计算
|
|
||||||
```
|
|
||||||
用户: "计算 2的10次方 加上 16的平方根"
|
|
||||||
→ LLM调用 math_calculate("pow(2, 10) + sqrt(16)")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 场景4: 文件处理
|
|
||||||
```
|
|
||||||
用户: "读取config.json文件并解析"
|
|
||||||
→ LLM调用 file_read 读取文件
|
|
||||||
→ LLM调用 json_process 解析内容
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 安全限制
|
|
||||||
|
|
||||||
1. **文件操作限制**:
|
|
||||||
- 只能读写项目目录下的文件
|
|
||||||
- 不允许访问系统敏感文件
|
|
||||||
|
|
||||||
2. **数学计算限制**:
|
|
||||||
- 只允许安全的数学函数
|
|
||||||
- 不允许执行任意代码
|
|
||||||
|
|
||||||
3. **HTTP请求限制**:
|
|
||||||
- 超时时间:30秒
|
|
||||||
- 建议在生产环境中添加域名白名单
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 如何启用工具
|
|
||||||
|
|
||||||
1. 在工作流编辑器中,选择LLM节点
|
|
||||||
2. 打开"工具"标签页
|
|
||||||
3. 启用"启用工具调用"开关
|
|
||||||
4. 选择需要的工具(可多选)
|
|
||||||
5. 保存配置
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 工具调用流程
|
|
||||||
|
|
||||||
```
|
```
|
||||||
用户输入
|
用户输入
|
||||||
↓
|
-> LLM 节点(启用工具)
|
||||||
LLM节点(启用工具)
|
-> AgentToolManager 过滤可用工具(include/exclude 白名单)
|
||||||
↓
|
-> LLM 分析需求,生成 function_call
|
||||||
LLM分析需求,决定调用哪个工具
|
-> ToolRegistry.execute_tool() 分发
|
||||||
↓
|
-> 内置函数工具
|
||||||
执行工具
|
-> HTTP 工具
|
||||||
↓
|
-> 代码工具
|
||||||
工具返回结果
|
-> 工作流工具
|
||||||
↓
|
-> 结果返回 LLM
|
||||||
LLM基于结果生成最终回复
|
-> LLM 生成最终回复
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 如何启用
|
||||||
|
|
||||||
|
1. 工作流编辑器中,选择 LLM 节点
|
||||||
|
2. 打开工具配置,启用工具调用
|
||||||
|
3. 从 56 个工具中选择所需工具(可多选)
|
||||||
|
4. 保存配置
|
||||||
|
|
||||||
|
创建 Agent 时通过 `include_tools` 控制可用工具范围:设为空数组 `[]` 或不传则默认启用全部 56 个工具。
|
||||||
|
|
||||||
|
## 自定义工具扩展
|
||||||
|
|
||||||
|
除 56 个内置工具外,支持通过 API 动态注册:
|
||||||
|
|
||||||
|
| 类型 | 方式 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| HTTP 工具 | `POST /api/v1/tools` | URL 模板 + 参数占位符 |
|
||||||
|
| 代码工具 | `code_tool_create` | 已验证的 Python/JS 代码持久化为工具 |
|
||||||
|
| 工作流工具 | 工作流封装 | 将已有工作流封装为可调用工具 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**最后更新**: 2026-01-23
|
**工具总数**: 56 个(内置),支持自定义扩展
|
||||||
**工具总数**: 8个
|
|
||||||
|
|||||||
@@ -1,27 +1,23 @@
|
|||||||
# 🚀 快速开始指南
|
# 快速开始指南
|
||||||
|
|
||||||
> **Quick Start Guide**
|
本文档指导在 5 分钟内完成天工智能体平台的本地部署与启动。
|
||||||
|
|
||||||
本文档指导您在 5 分钟内完成天工智能体平台的本地部署与启动。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 前置要求
|
## 前置要求
|
||||||
|
|
||||||
| 组件 | 版本要求 | 说明 |
|
| 组件 | 版本 | 说明 |
|
||||||
|:----|:---------|:-----|
|
|------|------|------|
|
||||||
| Node.js | 18+ | JavaScript 运行时 |
|
| Node.js | 18+ | JavaScript 运行时 |
|
||||||
| pnpm | 8+ | 前端包管理器 |
|
| pnpm | 8+ | 前端包管理器 |
|
||||||
| Python | 3.11+ | 后端运行时 |
|
| Python | 3.11+ | 后端运行时 |
|
||||||
| Docker & Docker Compose | 最新版 | 容器化部署(推荐) |
|
| Docker & Docker Compose | 最新 | 容器化部署(推荐) |
|
||||||
| MySQL | 8.0+ | 使用腾讯云数据库 |
|
| MySQL | 8.0+ | 可使用腾讯云数据库 |
|
||||||
| Redis | 7+ | 缓存与消息队列(可用 Docker) |
|
| Redis | 7+ | 缓存与消息队列(可用 Docker) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🐳 使用 Docker Compose(推荐)
|
## 使用 Docker Compose(推荐)
|
||||||
|
|
||||||
### 启动服务
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 启动所有服务
|
# 启动所有服务
|
||||||
@@ -34,20 +30,20 @@ docker-compose logs -f
|
|||||||
docker-compose down
|
docker-compose down
|
||||||
```
|
```
|
||||||
|
|
||||||
### 服务端口
|
### 服务端口(Docker 部署)
|
||||||
|
|
||||||
| 服务 | 端口 | 说明 |
|
| 服务 | 端口 | 说明 |
|
||||||
|:----|:----|:------|
|
|------|------|------|
|
||||||
| 前端 | `8038` | 浏览器访问 `http://localhost:8038` |
|
| 前端 (Nginx) | 8038 | 浏览器访问 `http://localhost:8038` |
|
||||||
| 后端 API | `8037` | API 服务 |
|
| 后端 API | 8037 | API 服务 |
|
||||||
| API 文档 | `8037/docs` | Swagger UI 交互式文档 |
|
| Swagger 文档 | 8037/docs | Swagger UI 交互式文档 |
|
||||||
| Redis | `6379` | 缓存服务(Docker) |
|
| Redis | 6379 | 缓存服务 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 💻 本地开发环境
|
## 本地开发环境
|
||||||
|
|
||||||
### 1️⃣ 前端启动
|
### 1. 前端启动
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
@@ -55,15 +51,23 @@ pnpm install
|
|||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
前端开发服务器将在 `http://localhost:8038` 启动,支持热重载。
|
前端开发服务器在 `http://localhost:3001` 启动,支持热重载,自动代理 `/api` 到 `http://127.0.0.1:8038`。
|
||||||
|
|
||||||
### 2️⃣ 后端启动
|
可通过环境变量覆盖代理目标:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# PowerShell
|
||||||
|
$env:AIAGENT_API_PROXY='http://127.0.0.1:8040'; npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 后端启动
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
|
|
||||||
# 创建并激活 Python 虚拟环境
|
# 创建并激活 Python 虚拟环境
|
||||||
python -m venv venv
|
python -m venv venv
|
||||||
|
|
||||||
# Windows
|
# Windows
|
||||||
venv\Scripts\activate
|
venv\Scripts\activate
|
||||||
# macOS / Linux
|
# macOS / Linux
|
||||||
@@ -74,37 +78,61 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
# 配置环境变量
|
# 配置环境变量
|
||||||
cp env.example .env
|
cp env.example .env
|
||||||
# ⚠️ 编辑 .env 文件,配置数据库连接等信息
|
# 编辑 .env 文件,配置数据库连接等信息
|
||||||
|
|
||||||
# 运行数据库迁移
|
# 运行数据库迁移
|
||||||
alembic upgrade head
|
alembic upgrade head
|
||||||
|
|
||||||
# 启动开发服务器
|
# 启动开发服务器(必须指定 --port 8038,与前端 Vite 代理目标一致)
|
||||||
uvicorn app.main:app --reload
|
uvicorn app.main:app --port 8038 --reload
|
||||||
|
|
||||||
# (新终端窗口)启动 Celery Worker
|
# 新终端窗口 — 启动 Celery Worker
|
||||||
celery -A app.core.celery_app worker --loglevel=info
|
celery -A app.core.celery_app worker --loglevel=info
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
### 本地开发端口
|
||||||
|
|
||||||
## ✅ 验证部署
|
| 服务 | 端口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
1. 浏览器访问 `http://localhost:8038` → 看到登录/注册页面
|
| 前端 (Vite) | 3001 | `http://localhost:3001` |
|
||||||
2. 浏览器访问 `http://localhost:8037/docs` → 看到 Swagger API 文档
|
| 后端 API | 8038 | `uvicorn app.main:app --port 8038 --reload` |
|
||||||
3. 尝试调用 `/health` 端点 → 返回 `{"status": "ok"}`
|
| Swagger 文档 | 8038/docs | `http://localhost:8038/docs` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ❗ 常见问题
|
## 快速验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 登录获取 token
|
||||||
|
curl -s -X POST http://localhost:8038/api/v1/auth/login \
|
||||||
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||||
|
-d 'username=admin&password=123456'
|
||||||
|
|
||||||
|
# 测试对话
|
||||||
|
curl -s -X POST http://localhost:8038/api/v1/agent-chat/bare \
|
||||||
|
-H "Authorization: Bearer <TOKEN>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"message":"你好"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器验证:
|
||||||
|
|
||||||
|
1. 访问 `http://localhost:3001` — 看到登录页面
|
||||||
|
2. 访问 `http://localhost:8038/docs` — 看到 Swagger API 文档
|
||||||
|
3. 调用 `/health` 端点 — 返回 `{"status": "ok"}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
| 问题 | 可能原因 | 解决方案 |
|
| 问题 | 可能原因 | 解决方案 |
|
||||||
|:----|:---------|:---------|
|
|------|---------|---------|
|
||||||
| 数据库连接失败 | `.env` 中数据库配置错误 | 检查 `DATABASE_URL` 配置 |
|
| 数据库连接失败 | .env 中配置错误 | 检查 DATABASE_URL |
|
||||||
| 端口被占用 | 本地已有服务占用端口 | 修改 `docker-compose.dev.yml` 中的端口映射 |
|
| 端口被占用 | 本地已有服务占用 | 修改端口或停用冲突进程 |
|
||||||
| pnpm 安装失败 | Node.js 版本过低 | 升级 Node.js 至 18+ |
|
| pnpm 安装失败 | Node.js 版本过低 | 升级至 18+ |
|
||||||
| 虚拟环境激活失败 | Python 未安装 | 确认 `python --version` >= 3.11 |
|
| 虚拟环境激活失败 | Python 未安装 | 确认 `python --version` >= 3.11 |
|
||||||
|
| 前端请求 500 | Vite 代理目标端口错误 | 确认后端启动在 8038,或设置 AIAGENT_API_PROXY |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
> 遇到其他问题?请参考 [部署与运维指南](./deployment-guide.md) 或提交 [Issue](#)。
|
> 参考:[部署与运维指南](./deployment-guide.md)
|
||||||
|
|||||||
391
docs/产品化落地方案.md
Normal file
391
docs/产品化落地方案.md
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
# 豆包风格智能助手 — 产品化落地方案
|
||||||
|
|
||||||
|
> 从 AI Agent 到完整产品:App、语音、推送三大能力落地路线图
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、现状盘点
|
||||||
|
|
||||||
|
| 能力 | 后端工具 | 前端 | 状态 |
|
||||||
|
|------|---------|------|------|
|
||||||
|
| 语音转文字 | `speech_to_text` (API:OpenAI Whisper) | 无录音入口 | ⚠️ 工具存在,前端缺失 |
|
||||||
|
| 文字转语音 | `text_to_speech` (API:OpenAI TTS) | 无播放器 | ⚠️ 工具存在,前端缺失 |
|
||||||
|
| 通知推送 | `notify_user` (Main Agent) | 无推送UI | ⚠️ 工具存在,前端缺失 |
|
||||||
|
| 消息通知 | `Notification` 模型 + API | 无 | ⚠️ DB就绪,无消费端 |
|
||||||
|
| 移动App | — | 无 | ❌ 不存在 |
|
||||||
|
| 浏览器推送 | — | 无 | ❌ Service Worker 未配置 |
|
||||||
|
| 飞书消息 | 飞书 Bot 长连接 | — | ✅ 已有 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、App 客户端方案
|
||||||
|
|
||||||
|
### 2.1 技术选型
|
||||||
|
|
||||||
|
| 方案 | 优势 | 劣势 | 推荐度 |
|
||||||
|
|------|------|------|--------|
|
||||||
|
| **Flutter** | 一套代码双端、热重载、Dart易学 | 包体积较大 | ⭐⭐⭐⭐⭐ |
|
||||||
|
| React Native | JS生态、热更新、社区大 | 原生交互需桥接 | ⭐⭐⭐⭐ |
|
||||||
|
| **PWA** (渐进式Web) | 零安装、复用Vue代码、成本最低 | 功能受限(推送iOS) | ⭐⭐⭐⭐ |
|
||||||
|
| UniApp | 国内小程序+App一体 | 性能不如Flutter | ⭐⭐⭐ |
|
||||||
|
|
||||||
|
**推荐路径:PWA 先行(1周上线),Flutter 跟进(4周MVP)**
|
||||||
|
|
||||||
|
### 2.2 PWA 快速上线方案(第1周)
|
||||||
|
|
||||||
|
```
|
||||||
|
frontend/
|
||||||
|
├── public/
|
||||||
|
│ ├── manifest.json # PWA 配置(图标/名称/主题色)
|
||||||
|
│ └── sw.js # Service Worker(离线缓存+推送)
|
||||||
|
├── src/
|
||||||
|
│ ├── views/
|
||||||
|
│ │ └── MobileChat.vue # 移动端对话界面
|
||||||
|
│ └── utils/
|
||||||
|
│ └── push.ts # 浏览器推送注册
|
||||||
|
```
|
||||||
|
|
||||||
|
**manifest.json 示例:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "豆包智能助手",
|
||||||
|
"short_name": "豆包",
|
||||||
|
"start_url": "/?source=pwa",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"theme_color": "#4f46e5",
|
||||||
|
"icons": [
|
||||||
|
{"src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png"},
|
||||||
|
{"src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心改动:**
|
||||||
|
1. `vite.config.ts` 增加 `@vitejs/plugin-pwa` 插件
|
||||||
|
2. 新建 `MobileChat.vue` — 移动端全屏聊天界面(底部输入框+语音按钮+对话气泡)
|
||||||
|
3. 新建 `src/utils/push.ts` — 注册 Service Worker、请求通知权限
|
||||||
|
4. `index.html` 添加 `<link rel="manifest">` 和 `<meta name="theme-color">`
|
||||||
|
|
||||||
|
**代价:** ~200行新代码,前端依赖 +1 (`vite-plugin-pwa`)
|
||||||
|
|
||||||
|
### 2.3 Flutter App 方案(第2-5周)
|
||||||
|
|
||||||
|
```
|
||||||
|
doubao_app/
|
||||||
|
├── lib/
|
||||||
|
│ ├── main.dart # 入口
|
||||||
|
│ ├── app.dart # MaterialApp 配置
|
||||||
|
│ ├── models/
|
||||||
|
│ │ ├── message.dart # 消息模型
|
||||||
|
│ │ └── user.dart # 用户模型
|
||||||
|
│ ├── services/
|
||||||
|
│ │ ├── api_service.dart # HTTP 客户端(复用后端API)
|
||||||
|
│ │ ├── auth_service.dart # JWT 存储/刷新
|
||||||
|
│ │ ├── audio_service.dart # 录音 + 播放
|
||||||
|
│ │ └── push_service.dart # FCM/个推 注册
|
||||||
|
│ ├── pages/
|
||||||
|
│ │ ├── login_page.dart # 登录
|
||||||
|
│ │ ├── chat_page.dart # 对话主界面
|
||||||
|
│ │ ├── history_page.dart # 历史对话
|
||||||
|
│ │ └── settings_page.dart # 设置
|
||||||
|
│ └── widgets/
|
||||||
|
│ ├── chat_bubble.dart # 对话气泡
|
||||||
|
│ ├── voice_button.dart # 语音录制按钮
|
||||||
|
│ └── typing_indicator.dart # 输入状态
|
||||||
|
├── pubspec.yaml
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心功能实现:**
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// lib/services/api_service.dart
|
||||||
|
class ApiService {
|
||||||
|
static const baseUrl = 'http://101.43.95.130:8038/api/v1';
|
||||||
|
|
||||||
|
// 流式对话(SSE)
|
||||||
|
Stream<String> chatStream(String agentId, String message) async* {
|
||||||
|
final response = await http.Client().send(
|
||||||
|
http.Request('POST', Uri.parse('$baseUrl/agent-chat/$agentId/stream'))
|
||||||
|
..headers.addAll({'Authorization': 'Bearer $token', 'Content-Type': 'application/json'})
|
||||||
|
..body = jsonEncode({'message': message, 'streamlined': true}),
|
||||||
|
);
|
||||||
|
await for (final chunk in response.stream.transform(utf8.decoder)) {
|
||||||
|
// 解析 SSE data: {...} 事件
|
||||||
|
yield chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**代价:** ~1500行 Dart 代码,Flutter SDK + 依赖(dio, flutter_secure_storage, record, audioplayers, firebase_messaging)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、语音能力方案
|
||||||
|
|
||||||
|
### 3.1 需求拆解
|
||||||
|
|
||||||
|
```
|
||||||
|
语音输入(ASR) 语音输出(TTS)
|
||||||
|
┌──────────────────────┐ ┌──────────────────┐
|
||||||
|
│ 用户说话 │ │ AI回复文本 │
|
||||||
|
│ ↓ │ │ ↓ │
|
||||||
|
│ 前端录音 → Base64 │ │ 后端TTS → .mp3 │
|
||||||
|
│ ↓ │ │ ↓ │
|
||||||
|
│ 后端 speech_to_text │ │ 返回音频URL │
|
||||||
|
│ ↓ │ │ ↓ │
|
||||||
|
│ Whisper API 转文字 │ │ 前端播放器 │
|
||||||
|
│ ↓ │ │ │
|
||||||
|
│ 送入Agent对话 │ │ │
|
||||||
|
└──────────────────────┘ └──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 前端录音实现(Vue3)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/composables/useVoiceInput.ts
|
||||||
|
export function useVoiceInput() {
|
||||||
|
const isRecording = ref(false)
|
||||||
|
let mediaRecorder: MediaRecorder | null = null
|
||||||
|
const chunks: Blob[] = []
|
||||||
|
|
||||||
|
async function startRecording() {
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
|
||||||
|
mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' })
|
||||||
|
mediaRecorder.ondataavailable = (e) => chunks.push(e.data)
|
||||||
|
mediaRecorder.start()
|
||||||
|
isRecording.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopRecording(): Promise<Blob> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
mediaRecorder!.onstop = () => {
|
||||||
|
resolve(new Blob(chunks, { type: 'audio/webm' }))
|
||||||
|
chunks.length = 0
|
||||||
|
}
|
||||||
|
mediaRecorder!.stop()
|
||||||
|
mediaRecorder!.stream.getTracks().forEach(t => t.stop())
|
||||||
|
isRecording.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isRecording, startRecording, stopRecording }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 后端语音端点(新增)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/api/voice.py — 新增文件
|
||||||
|
@router.post("/voice/asr")
|
||||||
|
async def voice_to_text(
|
||||||
|
file: UploadFile = File(...),
|
||||||
|
current_user: User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""语音转文字 — 前端录音上传 → Whisper → 返回文本"""
|
||||||
|
audio_path = f"/tmp/{uuid4()}.webm"
|
||||||
|
with open(audio_path, "wb") as f:
|
||||||
|
f.write(await file.read())
|
||||||
|
text = await speech_to_text_tool(audio_path)
|
||||||
|
os.remove(audio_path)
|
||||||
|
return {"text": text}
|
||||||
|
|
||||||
|
@router.post("/voice/tts")
|
||||||
|
async def text_to_voice(
|
||||||
|
req: TTSRequest,
|
||||||
|
current_user: User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""文字转语音 — 返回音频文件URL"""
|
||||||
|
output_path = f"uploads/tts/{uuid4()}.mp3"
|
||||||
|
result = await text_to_speech_tool(req.text, req.voice, output_path)
|
||||||
|
return {"audio_url": f"/api/v1/uploads/tts/{output_path}"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**代价:** 后端 ~80行新增,前端 ~60行 composable
|
||||||
|
|
||||||
|
### 3.4 语音交互优化
|
||||||
|
|
||||||
|
| 优化点 | 方案 |
|
||||||
|
|--------|------|
|
||||||
|
| 流式TTS | OpenAI TTS 不支持流式,可换用 Edge-TTS(免费)或 ElevenLabs 流式API |
|
||||||
|
| VAD静音检测 | `@ricky0123/vad-web` — 前端自动检测说话结束,无需手动停止 |
|
||||||
|
| 打断对话 | 用户开始说话时中止当前TTS播放 + 打断LLM流式输出 |
|
||||||
|
| 音色选择 | 提供 6 种音色(alloy/echo/fable/onyx/nova/shimmer)切换 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、推送通知方案
|
||||||
|
|
||||||
|
### 4.1 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐
|
||||||
|
│ Agent 完成任务 │ → │ Notification │ → │ FCM / 个推 │
|
||||||
|
│ schedule 触发 │ │ DB 表 + API │ │ Push Service │
|
||||||
|
│ notify_user 工具 │ │ │ │ ↓ │
|
||||||
|
└─────────────────┘ └──────────────┘ │ 手机/浏览器 │
|
||||||
|
└──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 通知类型定义
|
||||||
|
|
||||||
|
| 类型 | 触发场景 | 优先级 |
|
||||||
|
|------|---------|--------|
|
||||||
|
| `agent_reply` | Agent 完成回复 | 中 |
|
||||||
|
| `schedule_done` | 定时任务执行完毕 | 中 |
|
||||||
|
| `goal_milestone` | 目标达成阶段性成果 | 高 |
|
||||||
|
| `approval_required` | 工具调用需要人类审批 | 紧急 |
|
||||||
|
| `alert` | 系统告警触发 | 紧急 |
|
||||||
|
| `daily_summary` | 每日 AI 摘要推送 | 低 |
|
||||||
|
|
||||||
|
### 4.3 浏览器推送(PWA)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// public/sw.js
|
||||||
|
self.addEventListener('push', (event) => {
|
||||||
|
const data = event.data?.json() || {}
|
||||||
|
self.registration.showNotification(data.title, {
|
||||||
|
body: data.body,
|
||||||
|
icon: '/icons/icon-192.png',
|
||||||
|
badge: '/icons/badge-72.png',
|
||||||
|
data: { url: data.url || '/' },
|
||||||
|
actions: data.actions || [],
|
||||||
|
requireInteraction: data.priority === 'urgent',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
self.addEventListener('notificationclick', (event) => {
|
||||||
|
event.notification.close()
|
||||||
|
event.waitUntil(clients.openWindow(event.notification.data.url))
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/utils/push.ts
|
||||||
|
export async function subscribeToPush(): Promise<string | null> {
|
||||||
|
const reg = await navigator.serviceWorker.ready
|
||||||
|
const sub = await reg.pushManager.subscribe({
|
||||||
|
userVisibleOnly: true,
|
||||||
|
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
|
||||||
|
})
|
||||||
|
// 将 subscription 发送到后端 /api/v1/push/subscribe
|
||||||
|
await api.post('/push/subscribe', { subscription: sub.toJSON() })
|
||||||
|
return sub.endpoint
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 后端推送服务(新增)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/services/push_service.py — 新增文件
|
||||||
|
import json
|
||||||
|
from pywebpush import webpush, WebPushException
|
||||||
|
|
||||||
|
VAPID_CLAIMS = {
|
||||||
|
"sub": "mailto:admin@tiangong.ai"
|
||||||
|
}
|
||||||
|
|
||||||
|
async def send_web_push(user_id: str, title: str, body: str, url: str = "/"):
|
||||||
|
"""向用户的所有浏览器端点推送通知"""
|
||||||
|
subscriptions = await get_user_push_subscriptions(user_id)
|
||||||
|
for sub in subscriptions:
|
||||||
|
try:
|
||||||
|
webpush(
|
||||||
|
subscription_info=json.loads(sub.endpoint_data),
|
||||||
|
data=json.dumps({"title": title, "body": body, "url": url}),
|
||||||
|
vapid_private_key=VAPID_PRIVATE_KEY,
|
||||||
|
vapid_claims=VAPID_CLAIMS,
|
||||||
|
)
|
||||||
|
except WebPushException:
|
||||||
|
# 端点失效,标记删除
|
||||||
|
await mark_subscription_expired(sub.id)
|
||||||
|
```
|
||||||
|
|
||||||
|
**代价:** 后端 ~120行,新增依赖 `pywebpush`,新增 `push_subscriptions` 表
|
||||||
|
|
||||||
|
### 4.5 App 推送(FCM/个推)
|
||||||
|
|
||||||
|
Flutter 侧接入 `firebase_messaging`:
|
||||||
|
```dart
|
||||||
|
// 注册 FCM token
|
||||||
|
final token = await FirebaseMessaging.instance.getToken();
|
||||||
|
await api.post('/push/register-app', {'token': token, 'platform': 'android'});
|
||||||
|
|
||||||
|
// 前台消息处理
|
||||||
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||||
|
if (message.notification != null) {
|
||||||
|
showLocalNotification(message.notification!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Android 渠道配置:**
|
||||||
|
| 渠道ID | 名称 | 重要性 | 行为 |
|
||||||
|
|--------|------|--------|------|
|
||||||
|
| `agent_reply` | AI回复 | DEFAULT | 声音+状态栏 |
|
||||||
|
| `approval` | 需要审批 | HIGH | 声音+振动+悬浮 |
|
||||||
|
| `alert` | 系统告警 | URGENT | 全屏通知 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、落地路线图
|
||||||
|
|
||||||
|
```
|
||||||
|
Week 1 Week 2-3 Week 4-5 长期
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐
|
||||||
|
│ ██ PWA 快速上线 │ │ ██ 语音交互 │ │ ██ Flutter App │ │ 多模态输入 │
|
||||||
|
│ │ │ │ │ │ │ │
|
||||||
|
│ • manifest.json │ │ • ASR 前端录音 │ │ • Flutter工程 │ │ • 图片上传 │
|
||||||
|
│ • ServiceWorker │ │ • TTS 播放器 │ │ • 对话主界面 │ │ • 文档分析 │
|
||||||
|
│ • MobileChat.vue│ │ • 语音API端点 │ │ • 推送接入FCM │ │ • 拍照识别 │
|
||||||
|
│ • 浏览器推送 │ │ • VAD静音检测 │ │ • Android/iOS │ │ • 视频理解 │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘ └──────────────┘
|
||||||
|
~200行前端改动 ~200行前后端 ~1500行Flutter ~500行
|
||||||
|
1天 3天 2周 按需
|
||||||
|
```
|
||||||
|
|
||||||
|
### 里程碑验收标准
|
||||||
|
|
||||||
|
| 里程碑 | 验收标准 |
|
||||||
|
|--------|---------|
|
||||||
|
| M1: PWA上线 | 手机浏览器打开 → 添加到主屏幕 → 能对话 → 能收推送 |
|
||||||
|
| M2: 语音可用 | 点击麦克风 → 说话 → 自动转文字 → AI回复可朗读 |
|
||||||
|
| M3: App上架 | Flutter App 在 TestFlight/应用宝 可下载安装 |
|
||||||
|
| M4: 完整产品 | 拍照→AI分析 + 语音对话 + 推送通知 + 离线缓存 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、工作量估算
|
||||||
|
|
||||||
|
| 模块 | 内容 | 工作量 |
|
||||||
|
|------|------|--------|
|
||||||
|
| PWA | manifest + SW + MobileChat + 推送注册 | 1天 |
|
||||||
|
| 语音ASR | 前端录音composable + 后端voice/asr端点 | 0.5天 |
|
||||||
|
| 语音TTS | 前端播放器 + 后端voice/tts端点 | 0.5天 |
|
||||||
|
| 浏览器推送 | sw.js推送处理 + push.ts注册 + 后端推送服务 + push_subscriptions表 | 1天 |
|
||||||
|
| Flutter App | 登录/对话/历史/设置/推送/语音/图标/上架 | 2周 |
|
||||||
|
| 后端推送增强 | VAPID配置 + FCM集成 + 通知策略引擎 | 1天 |
|
||||||
|
| 测试联调 | 端到端测试 + 兼容性测试 | 2天 |
|
||||||
|
| **合计** | | **约3周** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、当前可用能力速查
|
||||||
|
|
||||||
|
以下工具后端已存在,前端接入即可用:
|
||||||
|
|
||||||
|
| 工具名 | 功能 | 前端需要 | 难度 |
|
||||||
|
|--------|------|---------|------|
|
||||||
|
| `speech_to_text` | Whisper 语音转文字 | 录音按钮 + 上传 | ★ |
|
||||||
|
| `text_to_speech` | OpenAI TTS 文字转语音 | 播放按钮 + 音频播放 | ★ |
|
||||||
|
| `notify_user` | Main Agent 通知 | 通知中心UI | ★★ |
|
||||||
|
| `image_vision` | 图片视觉理解 | 图片上传组件 | ★ |
|
||||||
|
| `image_ocr` | 图片文字提取 | 图片上传+结果展示 | ★ |
|
||||||
|
| `deploy_push` | 部署推送 | 一键部署按钮 | ★ |
|
||||||
|
| `feishu_*` | 飞书系列(7个工具) | — | ✅ 已可用 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **结论:** 从 AI Agent 到完整产品,核心 AI 能力已经超越真豆包的部分维度。剩下的工作主要是 **前端交互层** 和 **分发渠道**,成本可控,3周可达 MVP 水平。
|
||||||
211
docs/飞书智能体配置手册.md
Normal file
211
docs/飞书智能体配置手册.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# 飞书智能体配置手册
|
||||||
|
|
||||||
|
天工智能体平台通过 6 个飞书应用对外提供 AI 对话服务,每个应用拥有独立的身份、Agent 和长连接通道。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、架构概览
|
||||||
|
|
||||||
|
```
|
||||||
|
飞书客户端
|
||||||
|
│
|
||||||
|
├── 苹果 (默认) ──→ WS Handler ──→ 智能聊天助手(完整示例)
|
||||||
|
├── 橙子 ──→ orange_ws_handler.py ──→ 橙子助手
|
||||||
|
├── 苏瑶 ──→ suyao_ws_handler.py ──→ 豆包风格智能助手
|
||||||
|
├── 甜甜 ──→ tiantian_ws_handler.py ──→ 苏瑶3号
|
||||||
|
├── 灵犀 ──→ lingxi_ws_handler.py ──→ 智能学习助手1号
|
||||||
|
└── 人参果 ──→ renshenguo_ws_handler.py ──→ AI学习助手
|
||||||
|
```
|
||||||
|
|
||||||
|
每个机器人通过飞书长连接(WebSocket)独立接收消息,实时查询数据库获取 Agent 配置,每次对话自动使用最新配置,无需重启。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、应用凭证
|
||||||
|
|
||||||
|
| 助手 | App ID | App Secret | Agent ID |
|
||||||
|
|------|--------|------------|----------|
|
||||||
|
| 苹果 | `cli_a97f3e2ecaf81cba` | `KtS5Df...` | `78ba9dfb-31fa-4550-833b-c44d4378cf6c` |
|
||||||
|
| 橙子 | `cli_a97f1271ec345cc6` | `FrGxzz...` | `ae27238a-705e-4a5a-bbf0-6904087c5881` |
|
||||||
|
| 苏瑶 | `cli_a97f5668d5f8dcb6` | `oJQ9LF...` | `be657a81-74f8-4f19-8c64-d7d12a1b086c` |
|
||||||
|
| 甜甜 | `cli_a97f42fdaef8dcb0` | `IU0Mxb...` | `f53e6967-acc2-45e8-9d37-13f4724a729a` |
|
||||||
|
| 灵犀 | `cli_a97ca9d90578dceb` | `5lRxnv...` | `03f14650-2cbf-4245-b3b9-9ebce25a68a9` |
|
||||||
|
| 人参果 | `cli_a9709d5dc4389cb3` | `sa0HkQ...` | `7df49808-a3d3-4049-afbc-7602e6f58890` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、Agent 配置详情
|
||||||
|
|
||||||
|
### 3.1 苹果(默认飞书机器人)
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | 智能聊天助手(完整示例) |
|
||||||
|
| Agent ID | `78ba9dfb-31fa-4550-833b-c44d4378cf6c` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 120 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
### 3.2 橙子
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | 橙子助手 |
|
||||||
|
| Agent ID | `ae27238a-705e-4a5a-bbf0-6904087c5881` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 2 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
### 3.3 苏瑶
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | 豆包风格智能助手 |
|
||||||
|
| Agent ID | `be657a81-74f8-4f19-8c64-d7d12a1b086c` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 2 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
### 3.4 甜甜
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | 苏瑶3号 |
|
||||||
|
| Agent ID | `f53e6967-acc2-45e8-9d37-13f4724a729a` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 2 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
### 3.5 灵犀
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | 智能学习助手1号 |
|
||||||
|
| Agent ID | `03f14650-2cbf-4245-b3b9-9ebce25a68a9` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 8 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
### 3.6 人参果
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|------|------|
|
||||||
|
| Agent 名称 | AI学习助手 |
|
||||||
|
| Agent ID | `7df49808-a3d3-4049-afbc-7602e6f58890` |
|
||||||
|
| 模型 | **deepseek-v4-pro** |
|
||||||
|
| 温度 | 0.8 |
|
||||||
|
| 最大迭代 | 15 |
|
||||||
|
| 状态 | published |
|
||||||
|
| 版本 | 7 |
|
||||||
|
| 提示词 | 豆包 6 大特质(989 字) |
|
||||||
|
| 工具 | 全部 56 个 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、核心能力对比
|
||||||
|
|
||||||
|
| 能力 | 苹果 | 橙子 | 苏瑶 | 甜甜 | 灵犀 | 人参果 |
|
||||||
|
|------|:--:|:--:|:--:|:--:|:--:|:--:|
|
||||||
|
| 模型 | **pro** | **pro** | **pro** | **pro** | **pro** | **pro** |
|
||||||
|
| 全 56 工具 | - | Y | Y | Y | Y | - |
|
||||||
|
| 温暖对话 | - | Y | Y | Y | Y | - |
|
||||||
|
| 知识问答+搜索 | - | Y | Y | Y | Y | - |
|
||||||
|
| 多模态理解 | - | Y | Y | Y | Y | - |
|
||||||
|
| 创意写作 | - | Y | Y | Y | Y | - |
|
||||||
|
| 代码辅助 | - | Y | Y | Y | Y | - |
|
||||||
|
| 情感陪伴 | - | Y | Y | Y | Y | - |
|
||||||
|
| 对话压缩(三级) | Y | Y | Y | Y | Y | Y |
|
||||||
|
| 向量语义记忆 | Y | Y | Y | Y | Y | Y |
|
||||||
|
| DB 持久化 | Y | Y | Y | Y | Y | Y |
|
||||||
|
| 自主学习 | Y | Y | Y | Y | Y | Y |
|
||||||
|
| 飞书文档 | - | Y | Y | Y | Y | - |
|
||||||
|
| 飞书日程 | - | Y | Y | Y | Y | - |
|
||||||
|
| 飞书审批 | - | Y | Y | Y | Y | - |
|
||||||
|
| 定时任务 | - | Y | Y | Y | Y | - |
|
||||||
|
| 部署推送 | - | Y | Y | Y | Y | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、记忆与对话连续性
|
||||||
|
|
||||||
|
所有飞书机器人的 Agent 均运行在增强版 AgentRuntime 上,享有统一的三级记忆架构:
|
||||||
|
|
||||||
|
### 5.1 对话自动压缩
|
||||||
|
|
||||||
|
| 压缩级别 | 触发阈值 | 机制 | 效果 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| MicroCompact | 窗口 70% | 旧工具结果替换为桩标记 | 回收 30-50% token |
|
||||||
|
| FullCompact | 窗口 85% | LLM 摘要替换旧对话片段 | 进一步压缩 |
|
||||||
|
| ReactiveCompact | 窗口 95% | API 报错后被动触发 | 最终兜底 |
|
||||||
|
|
||||||
|
熔断保护:连续压缩失败 3 次自动停止。受保护的工具(file_write / send_email / deploy_push 等 14 个)绝不压缩。
|
||||||
|
|
||||||
|
### 5.2 记忆配置
|
||||||
|
|
||||||
|
| 配置项 | 默认值 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| max_history_messages | 20 | 注入 LLM 上下文的最大消息数 |
|
||||||
|
| persist_to_db | True | 会话消息写入 MySQL |
|
||||||
|
| vector_memory_enabled | True | 向量语义检索历史消息 |
|
||||||
|
| vector_memory_top_k | 5 | 每次检索最相关的 top 5 条 |
|
||||||
|
| learning_enabled | True | 从工具调用中自主学习模式 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、工作量记录
|
||||||
|
|
||||||
|
| 日期 | 操作 | 受影响 |
|
||||||
|
|------|------|--------|
|
||||||
|
| 2026-06-13 | 创建豆包风格智能助手(deepseek-v4-pro) | 新建 |
|
||||||
|
| 2026-06-13 | 橙子升级:flash→pro + 56工具 + 豆包提示词 | 橙子 v2 |
|
||||||
|
| 2026-06-13 | 灵犀升级:flash→pro + 56工具 + 豆包提示词 | 灵犀 v8 |
|
||||||
|
| 2026-06-13 | 甜甜升级:flash→pro + 56工具 + 豆包提示词 | 甜甜 v2 |
|
||||||
|
| 2026-06-13 | 苏瑶绑定豆包风格智能助手 | 苏瑶 v2 |
|
||||||
|
| 2026-06-13 | 苹果升级:chat→pro + 56工具 + draft→published | 苹果 v120 |
|
||||||
|
| 2026-06-13 | 人参果升级:flash→pro + 56工具 | 人参果 v7 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、待处理事项
|
||||||
|
|
||||||
|
| 优先级 | 事项 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| - | ~~苹果升级~~ | 已完成:deepseek-chat → deepseek-v4-pro,draft → published (v120) |
|
||||||
|
| - | ~~人参果升级~~ | 已完成:deepseek-v4-flash → deepseek-v4-pro (v7) |
|
||||||
|
| P2 | 苹果个性 Agent | 当前复用豆包提示词,可创建苹果专属人设 |
|
||||||
|
| P2 | 人参果个性 Agent | 当前复用豆包提示词,可创建学习场景专用人设 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、配置文件路径
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `backend/.env` | 飞书 App ID / Secret / Agent ID 绑定 |
|
||||||
|
| `backend/app/services/*_ws_handler.py` | 各机器人 WS 消息处理 |
|
||||||
|
| `backend/app/services/*_app_service.py` | 各机器人消息发送服务 |
|
||||||
|
| `backend/app/services/agent_schedule_service.py` | 定时任务通过各 App 推送 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> 最后更新:2026-06-13
|
||||||
Reference in New Issue
Block a user