From a7512a54234ba0eb74218dbb097a1dfb28baa570 Mon Sep 17 00:00:00 2001 From: renjianbo <18691577328@163.com> Date: Sat, 13 Jun 2026 21:58:10 +0800 Subject: [PATCH] docs: update 3 reference docs + add Android design, Feishu bot config, productization plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- docs/android-app-design.md | 720 ++++++++++++++++++++++++++++++++++ docs/api-reference.md | 586 ++++++++++++++------------- docs/features/内置工具列表.md | 406 +++++++------------ docs/quickstart.md | 104 +++-- docs/产品化落地方案.md | 391 ++++++++++++++++++ docs/飞书智能体配置手册.md | 211 ++++++++++ 6 files changed, 1814 insertions(+), 604 deletions(-) create mode 100644 docs/android-app-design.md create mode 100644 docs/产品化落地方案.md create mode 100644 docs/飞书智能体配置手册.md diff --git a/docs/android-app-design.md b/docs/android-app-design.md new file mode 100644 index 0000000..0e48fcc --- /dev/null +++ b/docs/android-app-design.md @@ -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> // 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 + + // --- 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 = 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 显示,光标闪烁 | +| 底部输入栏 | 文本输入框 + 语音按钮 + 发送按钮 + 加号(图片/文件) | +| 空状态 | 首次进入显示"你好,我是 " + 快捷提问建议 | + +**状态管理(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 | diff --git a/docs/api-reference.md b/docs/api-reference.md index 52079fe..aa2f875 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -1,403 +1,391 @@ -# 🔌 API 参考文档 +# API 参考文档 -> **API Reference** +天工智能体平台后端 RESTful API 接口规范。所有 API 前缀为 `/api/v1`。 -本文档描述了天工智能体平台后端 RESTful API 接口规范。所有 API 均通过 Nginx 反向代理暴露,前缀为 `/api/v1`。 - -> 💡 **交互式文档**:启动后端服务后,可访问 `http://localhost:8037/docs` 查看 Swagger UI 文档。 +启动后端后访问 Swagger UI 可查看完整接口列表并在线调试。 --- -## 一、通用规范 +## 通用规范 ### 基础 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 Authorization: Bearer ``` +Token 通过登录接口获取。 + ### 响应格式 -```json -// 成功响应 -{ - "code": 200, - "message": "success", - "data": { ... } -} +成功响应直接返回 Pydantic 模型序列化 JSON,无外层包装: -// 错误响应 -{ - "code": 40001, - "message": "用户不存在", - "data": null -} +```json +{"access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "bearer"} ``` -### 通用错误码 +错误响应: -| 状态码 | 错误码 | 说明 | -|:------|:-------|:------| -| 200 | 200 | 请求成功 | -| 400 | 40000 | 请求参数错误 | -| 401 | 40100 | 未认证(Token 缺失或过期) | -| 403 | 40300 | 无权限访问 | -| 404 | 40400 | 资源不存在 | -| 500 | 50000 | 服务器内部错误 | +```json +{"error": "ERROR_CODE", "message": "human readable message"} +``` + +### ID 格式 + +所有主键(Agent / Workflow / Execution / Goal / Task 等)均为 UUID 字符串(36 字符),不是整数。 --- -## 二、用户模块 +## 认证模块 `/api/v1/auth` -### 2.1 用户注册 +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/auth/register` | 用户注册(email + password + nickname) | +| POST | `/auth/login` | 登录,返回 access_token | +| GET | `/auth/me` | 获取当前用户信息(需 Bearer Token) | -注册新用户账号。 +### 登录 ```http -POST /api/v1/users/register +POST /api/v1/auth/login +Content-Type: application/x-www-form-urlencoded ``` -**请求体:** - | 参数 | 类型 | 必填 | 说明 | -|:-----|:-----|:-----|:------| -| `email` | string | ✅ | 邮箱地址 | -| `password` | string | ✅ | 密码(至少 8 位,含字母和数字) | -| `nickname` | string | ❌ | 用户昵称 | +|------|------|------|------| +| username | string | 是 | 用户名 | +| password | string | 是 | 密码 | -**请求示例:** +响应: ```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" - } + "access_token": "eyJhbGciOiJIUzI1NiIs...", + "token_type": "bearer" } ``` --- -### 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 -``` - -**响应示例:** - -```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 POST /api/v1/agents +Authorization: Bearer +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 { - "name": "智能客服助手", - "description": "用于解答常见产品问题", - "prompt_template": "你是一个专业的客服助手...", + "name": "智能体名称", + "description": "描述", + "system_prompt": "系统提示词...", "model_config": { "provider": "openai", - "model_name": "gpt-4o", - "temperature": 0.5, - "max_tokens": 2048 + "model_name": "deepseek-v4-pro", + "temperature": 0.8 + }, + "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 -GET /api/v1/agents?page=1&page_size=20 - +POST /api/v1/agent-chat/{agent_id} +Authorization: Bearer +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 | ❌ | 智能体名称 | -| `description` | string | ❌ | 智能体描述 | -| `prompt_template` | string | ❌ | 系统提示词 | -| `model_config` | object | ❌ | 模型配置 | +|------|------|------|------| +| message | string | 是 | 用户消息 | +| session_id | string | 否 | 会话 ID,用于恢复上下文 | +| streamlined | boolean | 否 | 是否精简输出 | + +### 流式对话 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 -POST /api/v1/conversations -``` - -**请求体:** - -| 参数 | 类型 | 必填 | 说明 | -|:-----|:-----|:-----|:------| -| `agent_id` | integer | ✅ | 关联的智能体 ID | -| `title` | string | ❌ | 会话标题(可选) | +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/knowledge-bases` | 知识库列表 | +| 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` | 语义搜索 | +| POST | `/knowledge-bases/{kb_id}/rag` | RAG 检索增强生成 | --- -### 4.2 发送消息 +## 工具模块 `/api/v1/tools` -向指定对话发送消息,支持流式响应(SSE)。 - -```http -POST /api/v1/conversations/{conversation_id}/messages -``` - -**请求体:** - -| 参数 | 类型 | 必填 | 说明 | -|:-----|:-----|:-----|:------| -| `content` | string | ✅ | 用户消息内容 | - -**流式响应(SSE):** - -``` -data: {"type": "token", "content": "你好"} -data: {"type": "token", "content": ","} -data: {"type": "token", "content": "请问有什么可以帮您?"} -data: {"type": "done"} -data: {"type": "error", "content": "..."} -``` +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/tools` | 工具列表 | +| 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 工具 | +| POST | `/tools/test/code` | 测试代码工具 | +| POST | `/tools/{tool_id}/use` | 调用工具 | --- -### 4.3 获取对话历史 +## 目标与任务 -```http -GET /api/v1/conversations/{conversation_id}/messages?page=1&page_size=50 -``` +### 目标 `/api/v1/goals` + +| 方法 | 路径 | 说明 | +|------|------|------| +| 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 /api/v1/knowledge/documents/upload -``` - -**请求格式:** `multipart/form-data` - -| 参数 | 类型 | 必填 | 说明 | -|:-----|:-----|:-----|:------| -| `file` | file | ✅ | 支持 PDF / TXT / Markdown | -| `agent_id` | integer | ✅ | 关联的智能体 ID | +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/swarm/run` | 运行 Agent 蜂群 | +| POST | `/swarm/run/stream` | 流式运行(SSE) | --- -### 5.2 文档检索 +## 通知模块 `/api/v1/notifications` -```http -POST /api/v1/knowledge/search -``` - -**请求体:** - -| 参数 | 类型 | 必填 | 说明 | -|:-----|:-----|:-----|:------| -| `query` | string | ✅ | 检索关键词 | -| `agent_id` | integer | ✅ | 限定知识库范围 | -| `top_k` | integer | ❌ | 返回条数(默认 5) | +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/notifications` | 通知列表 | +| GET | `/notifications/unread-count` | 未读数量 | +| PUT | `/notifications/{id}/read` | 标记已读 | +| PUT | `/notifications/read-all` | 全部已读 | +| DELETE | `/notifications/{id}` | 删除通知 | --- -## 六、健康检查 +## 飞书集成 `/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 -GET /api/v1/health +GET /health ``` -**响应:** - ```json { "status": "ok", "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) diff --git a/docs/features/内置工具列表.md b/docs/features/内置工具列表.md index 1897b8d..d1f7b6b 100644 --- a/docs/features/内置工具列表.md +++ b/docs/features/内置工具列表.md @@ -1,287 +1,159 @@ # 内置工具列表 -平台目前提供 **8个内置工具**,可以在LLM节点中启用工具调用来使用。 +平台提供 56 个内置工具,覆盖 11 个功能类别。工具定义在 `backend/app/services/builtin_tools.py`,启动时通过 ToolRegistry 自动注册。 -## 📋 工具列表 - -### 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" -} -``` +可在工作流 LLM 节点中启用工具调用,Agent 会自动选择合适的工具执行任务。 --- -### 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 | -**示例**: -```json -{ - "file_path": "backend/app/core/config.py" -} -``` +## 数据处理(7个) + +| 工具 | 功能 | 说明 | +|------|------|------| +| 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分析需求,决定调用哪个工具 - ↓ -执行工具 - ↓ -工具返回结果 - ↓ -LLM基于结果生成最终回复 + -> LLM 节点(启用工具) + -> AgentToolManager 过滤可用工具(include/exclude 白名单) + -> LLM 分析需求,生成 function_call + -> ToolRegistry.execute_tool() 分发 + -> 内置函数工具 + -> HTTP 工具 + -> 代码工具 + -> 工作流工具 + -> 结果返回 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 -**工具总数**: 8个 +**工具总数**: 56 个(内置),支持自定义扩展 diff --git a/docs/quickstart.md b/docs/quickstart.md index 471c4af..ec27e84 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -1,27 +1,23 @@ -# 🚀 快速开始指南 +# 快速开始指南 -> **Quick Start Guide** - -本文档指导您在 5 分钟内完成天工智能体平台的本地部署与启动。 +本文档指导在 5 分钟内完成天工智能体平台的本地部署与启动。 --- -## 📋 前置要求 +## 前置要求 -| 组件 | 版本要求 | 说明 | -|:----|:---------|:-----| +| 组件 | 版本 | 说明 | +|------|------|------| | Node.js | 18+ | JavaScript 运行时 | | pnpm | 8+ | 前端包管理器 | | Python | 3.11+ | 后端运行时 | -| Docker & Docker Compose | 最新版 | 容器化部署(推荐) | -| MySQL | 8.0+ | 使用腾讯云数据库 | +| Docker & Docker Compose | 最新 | 容器化部署(推荐) | +| MySQL | 8.0+ | 可使用腾讯云数据库 | | Redis | 7+ | 缓存与消息队列(可用 Docker) | --- -## 🐳 使用 Docker Compose(推荐) - -### 启动服务 +## 使用 Docker Compose(推荐) ```bash # 启动所有服务 @@ -34,20 +30,20 @@ docker-compose logs -f docker-compose down ``` -### 服务端口 +### 服务端口(Docker 部署) | 服务 | 端口 | 说明 | -|:----|:----|:------| -| 前端 | `8038` | 浏览器访问 `http://localhost:8038` | -| 后端 API | `8037` | API 服务 | -| API 文档 | `8037/docs` | Swagger UI 交互式文档 | -| Redis | `6379` | 缓存服务(Docker) | +|------|------|------| +| 前端 (Nginx) | 8038 | 浏览器访问 `http://localhost:8038` | +| 后端 API | 8037 | API 服务 | +| Swagger 文档 | 8037/docs | Swagger UI 交互式文档 | +| Redis | 6379 | 缓存服务 | --- -## 💻 本地开发环境 +## 本地开发环境 -### 1️⃣ 前端启动 +### 1. 前端启动 ```bash cd frontend @@ -55,15 +51,23 @@ pnpm install 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 cd backend # 创建并激活 Python 虚拟环境 python -m venv venv + # Windows venv\Scripts\activate # macOS / Linux @@ -74,37 +78,61 @@ pip install -r requirements.txt # 配置环境变量 cp env.example .env -# ⚠️ 编辑 .env 文件,配置数据库连接等信息 +# 编辑 .env 文件,配置数据库连接等信息 # 运行数据库迁移 alembic upgrade head -# 启动开发服务器 -uvicorn app.main:app --reload +# 启动开发服务器(必须指定 --port 8038,与前端 Vite 代理目标一致) +uvicorn app.main:app --port 8038 --reload -# (新终端窗口)启动 Celery Worker +# 新终端窗口 — 启动 Celery Worker celery -A app.core.celery_app worker --loglevel=info ``` ---- +### 本地开发端口 -## ✅ 验证部署 - -1. 浏览器访问 `http://localhost:8038` → 看到登录/注册页面 -2. 浏览器访问 `http://localhost:8037/docs` → 看到 Swagger API 文档 -3. 尝试调用 `/health` 端点 → 返回 `{"status": "ok"}` +| 服务 | 端口 | 说明 | +|------|------|------| +| 前端 (Vite) | 3001 | `http://localhost:3001` | +| 后端 API | 8038 | `uvicorn app.main:app --port 8038 --reload` | +| 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 " \ + -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` 配置 | -| 端口被占用 | 本地已有服务占用端口 | 修改 `docker-compose.dev.yml` 中的端口映射 | -| pnpm 安装失败 | Node.js 版本过低 | 升级 Node.js 至 18+ | +|------|---------|---------| +| 数据库连接失败 | .env 中配置错误 | 检查 DATABASE_URL | +| 端口被占用 | 本地已有服务占用 | 修改端口或停用冲突进程 | +| pnpm 安装失败 | Node.js 版本过低 | 升级至 18+ | | 虚拟环境激活失败 | Python 未安装 | 确认 `python --version` >= 3.11 | +| 前端请求 500 | Vite 代理目标端口错误 | 确认后端启动在 8038,或设置 AIAGENT_API_PROXY | --- -> 遇到其他问题?请参考 [部署与运维指南](./deployment-guide.md) 或提交 [Issue](#)。 +> 参考:[部署与运维指南](./deployment-guide.md) diff --git a/docs/产品化落地方案.md b/docs/产品化落地方案.md new file mode 100644 index 0000000..3802a9d --- /dev/null +++ b/docs/产品化落地方案.md @@ -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` 添加 `` 和 `` + +**代价:** ~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 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 { + 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 { + 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 水平。 diff --git a/docs/飞书智能体配置手册.md b/docs/飞书智能体配置手册.md new file mode 100644 index 0000000..c73d6ad --- /dev/null +++ b/docs/飞书智能体配置手册.md @@ -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