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:
renjianbo
2026-06-13 21:58:10 +08:00
parent ab1589921a
commit a7512a5423
6 changed files with 1814 additions and 604 deletions

720
docs/android-app-design.md Normal file
View 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 |

View File

@@ -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", "access_token": "eyJhbGciOiJIUzI1NiIs...",
"password": "Abc12345", "token_type": "bearer"
"nickname": "张三"
}
```
**响应示例:**
```json
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"email": "user@example.com",
"nickname": "张三",
"created_at": "2026-05-10T08:00:00Z"
}
} }
``` ```
--- ---
### 2.2 用户登录 ## 智能体模块 `/api/v1/agents`
获取 JWT 访问令牌。 | 方法 | 路径 | 说明 |
|------|------|------|
| 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/login
```
**请求体:**
| 参数 | 类型 | 必填 | 说明 |
|:-----|:-----|:-----|:------|
| `email` | string | ✅ | 邮箱地址 |
| `password` | string | ✅ | 密码 |
**响应示例:**
```json
{
"code": 200,
"message": "success",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 1800
}
}
```
---
### 2.3 Token 刷新
使用 Refresh Token 获取新的 Access Token。
```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)

View File

@@ -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个

View File

@@ -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)

View 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 水平。

View 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