清理: - 删除 34 份过时文档(gap reports/QA临时报告/验收报告/阶段性文档) - 删除 docs/.hermes/skills 第三方 skills 副本(16 文件) - 删除 skills-lock.json 目录归集: - 根目录仅保留 README.md 索引 - product/ — 产品与架构设计(PRD + ARCHITECTURE + P2设计文档 + AI/企业路线图) - tracking/ — Chatwoot parity 开发跟踪 - requirements/ — M01-M12 模块需求 - plans/ — 历史实现计划 - parity/ — 路由 parity 与前端契约 - qa/ — QA 报告与测试计划 - ops/ — 运维部署 命名规范: - 全小写 kebab-case,禁止全大写文件名 - product/tracking/ops 用 NN- 序号前缀 - requirements 用 MNN- 两位零填充模块号 - plans/qa 用 YYYY-MM-DD- 日期前缀 - requirements M1-M9 零填充为 M01-M09(修复字典序) 同步更新: - backend/cmd/route_parity/main.go 路径默认值 - backend/scripts/parity_frontend_smoke.sh 报告路径 - 所有 docs 内部交叉引用 - .gitignore 排除编译产物 (backend/gochat, backend/route_parity) - 新增迁移 000052/000053 - 前端 WS 相关修改
991 lines
41 KiB
Markdown
991 lines
41 KiB
Markdown
# GoChat 企业功能分析文档
|
||
|
||
> 版本:v1.1
|
||
> 更新日期:2026-07-09
|
||
> 目标:Chatwoot 企业版功能深度分析 + GoChat 商业收费功能构思 + CaptainAI/SSO/语音通话等功能设计方案
|
||
> 注:本文档最初生成于 2026-05-25,当时多数企业功能标记为 "Stub/未实现"。
|
||
> 截至更新日期,SLA/AuditLog/CustomRole/Company/AgentCapacity/AssignmentPolicy/Captain/Copilot 等已实现并通过 Chatwoot parity 对齐,详见 tracking/01-chatwoot-parity-tracker.md。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [Chatwoot 企业版功能全景分析](#一chatwoot-企业版功能全景分析)
|
||
2. [GoChat 商业收费模式构思](#二gochat-商业收费模式构思)
|
||
3. [CaptainAI 功能设计](#三captainai-功能设计)
|
||
4. [SSO 单点登录设计](#四sso-单点登录设计)
|
||
5. [语音通话功能设计](#五语音通话功能设计)
|
||
6. [企业版功能实施路线图](#六企业版功能实施路线图)
|
||
|
||
---
|
||
|
||
## 一、Chatwoot 企业版功能全景分析
|
||
|
||
### 1.1 Chatwoot 版本分层
|
||
|
||
Chatwoot 采取 **社区版(开源) + 企业版(付费)** 双轨模式:
|
||
|
||
| 版本 | 定价 | 定位 | 核心差异 |
|
||
|------|------|------|----------|
|
||
| **Community (开源)** | 免费 / 自部署 | 小团队、初创企业 | 基础客服功能,无 SLA/SSO/AI/语音 |
|
||
| **Cloud Pro** | $29/坐席/月 | 中型企业 | 云托管,含基础自动化 |
|
||
| **Cloud Enterprise** | $69/坐席/月 | 大型企业 | 全功能 + SSO + SLA + CaptainAI + 语音 |
|
||
| **Self-hosted Enterprise** | 按需报价 | 大型企业自部署 | 同 Cloud Enterprise,但自行部署 |
|
||
|
||
### 1.2 企业版独占功能清单
|
||
|
||
以下功能 **仅在 Enterprise 版本开放**,社区版无法使用:
|
||
|
||
| # | 功能 | 模块 | Chatwoot 实现 | GoChat 状态 |
|
||
|---|------|------|---------------|-------------|
|
||
| 1 | **SLA 策略** | SlaPolicy + AppliedSla + SlaEvent | 完整实现 | Stub/未实现 |
|
||
| 2 | **审计日志** | AuditLog | 完整实现 | Stub/未实现 |
|
||
| 3 | **自定义角色权限** | CustomRole | 完整实现 | Stub/未实现 |
|
||
| 4 | **公司/组织管理** | Company | 完整实现 | Stub/未实现 |
|
||
| 5 | **坐席容量策略** | AgentCapacityPolicy + InboxCapacityLimit | 完整实现 | Stub/未实现 |
|
||
| 6 | **语音通话** | Call + Voice 系列 Service | Twilio 集成 | Stub/未实现 |
|
||
| 7 | **SAML SSO** | AccountSamlSettings | 完整实现 | 部分(仅 Enable) |
|
||
| 8 | **Captain AI** | Captain::Assistant + Document + Scenario | 完整实现 | 已实现 |
|
||
| 9 | **Copilot** | SuggestReplies/Summarize/Translate | 完整实现 | 已实现 |
|
||
| 10 | **定时任务调度** | SidekiqCron | 完整实现 | 未实现 |
|
||
| 11 | **自动分配策略** | AssignmentPolicy | 完整实现 | Stub/未实现 |
|
||
| 12 | **Platform App / Partner API** | PlatformApp + Permissible | 完整实现 | Stub/未实现 |
|
||
| 13 | **AgentBot 智能机器人** | AgentBot + AgentBotInbox | 完整实现 | Stub/未实现 |
|
||
| 14 | **数据导入** | DataImport + DataImportJob | 完整实现 | 未实现 |
|
||
| 15 | **多品牌 Help Center** | Portal + Category + Article | 完整实现 | Stub/未实现 |
|
||
|
||
### 1.3 Chatwoot 功能授权机制
|
||
|
||
Chatwoot 通过以下三层机制控制企业版功能:
|
||
|
||
1. **Feature Flag**(`features.yml`):全局功能开关
|
||
- `enterprise` flag → 企业版总开关
|
||
- `saml` flag → SAML SSO 子开关
|
||
- `voice` flag → 语音通话子开关
|
||
|
||
2. **Billing Subscription**(云版):`InstallationConfig` + `Subscription` 模型
|
||
- 超级管理员配置订阅状态
|
||
- API 中间件检查订阅 → 未订阅则 403
|
||
|
||
3. **Policy 授权**:Pundit Policy 类
|
||
- `CustomRole` → 精细化角色权限
|
||
- `AccountPolicy` → 账户级操作权限
|
||
|
||
### 1.4 GoChat 当前差距总结
|
||
|
||
基于 `Gochat-vs-Chatwoot-Full-Comparison.md` 分析:
|
||
|
||
| 维度 | Chatwoot | GoChat | 差距 |
|
||
|------|----------|--------|------|
|
||
| API 路由数 | 327+ | 106 | **缺 221+(仅 32% 覆盖)** |
|
||
| Handler 方法数 | 150+ | 99 | **缺 51+** |
|
||
| 真实实现率 | 100% | 57% | **差 43%** |
|
||
| Stub/Placeholder | 0 | 37 | **全部需补实现** |
|
||
| 501 Not Implemented | 0 | 6 | **全部需补实现** |
|
||
| 消息队列调度 | Sidekiq 完整 | WorkerPool 全 stub | **不可用** |
|
||
| 渠道扩展机制 | 11 渠道 | 仅 2 渠道 | **缺 9 渠道** |
|
||
| 事件分发 | 9 Listener | 无真实 Listener | **事件驱动完全不可用** |
|
||
|
||
---
|
||
|
||
## 二、GoChat 商业收费模式构思
|
||
|
||
### 2.1 定价策略定位
|
||
|
||
GoChat 作为 Chatwoot 的 Go 语言高性能重写,应借鉴但超越 Chatwoot 的定价模式:
|
||
|
||
**核心差异化卖点:**
|
||
- Go 语言带来的 **10x 性能优势**(并发处理、内存占用、延迟)
|
||
- 更轻量的部署架构(单二进制 vs Ruby+Sidekiq+Redis 多进程)
|
||
- 开源友好 + 自部署优先
|
||
- AI 能力原生集成(而非插件式)
|
||
|
||
### 2.2 版本分层设计
|
||
|
||
| 版本 | 定价 | 目标用户 | 功能范围 |
|
||
|------|------|----------|----------|
|
||
| **Community(开源)** | 免费 | 小团队/个人/初创 | 核心客服功能:对话、联系人、收件箱、基础渠道、基础报表 |
|
||
| **Professional** | ¥99/坐席/月($15) | 中型企业 | +自动化规则 +高级报表 +批量操作 +Email渠道 +品牌定制 |
|
||
| **Enterprise** | ¥299/坐席/月($45) | 大型企业 | +SLA +SSO +语音通话 +CaptainAI +审计日志 +自定义角色 +坐席容量 |
|
||
| **Ultimate** | ¥599/坐席/月($90) | 超大型/政府 | +全功能 +私有部署支持 +定制开发 +专属SLA保障 |
|
||
|
||
### 2.3 功能-版本矩阵
|
||
|
||
| 功能 | Community | Professional | Enterprise | Ultimate |
|
||
|------|-----------|-------------|------------|----------|
|
||
| **对话管理** | ✅ | ✅ | ✅ | ✅ |
|
||
| **联系人 CRM** | ✅ | ✅ | ✅ | ✅ |
|
||
| **收件箱(5个)** | ✅ | ✅ 20个 | ✅ 无限 | ✅ 无限 |
|
||
| **坐席数** | 5 | 20 | 无限 | 无限 |
|
||
| **Telegram 渠道** | ✅ | ✅ | ✅ | ✅ |
|
||
| **WebWidget 渠道** | ✅ | ✅ | ✅ | ✅ |
|
||
| **API 渠道** | ✅ | ✅ | ✅ | ✅ |
|
||
| **Email 渠道** | - | ✅ | ✅ | ✅ |
|
||
| **WhatsApp 渠道** | - | ✅ | ✅ | ✅ |
|
||
| **Facebook 渠道** | - | ✅ | ✅ | ✅ |
|
||
| **Instagram 渠道** | - | ✅ | ✅ | ✅ |
|
||
| **Slack 渠道** | - | - | ✅ | ✅ |
|
||
| **Line 渠道** | - | - | ✅ | ✅ |
|
||
| **语音通话** | - | - | ✅ | ✅ |
|
||
| **SLA 策略** | - | - | ✅ | ✅ |
|
||
| **SAML SSO** | - | - | ✅ | ✅ |
|
||
| **Captain AI** | - | - | ✅ | ✅ |
|
||
| **Copilot 副驾驶** | - | - | ✅ | ✅ |
|
||
| **自定义角色权限** | - | - | ✅ | ✅ |
|
||
| **审计日志** | - | - | ✅ | ✅ |
|
||
| **坐席容量管理** | - | - | ✅ | ✅ |
|
||
| **公司/组织管理** | - | ✅ 基础 | ✅ 高级 | ✅ 高级 |
|
||
| **Help Center** | - | - | ✅ | ✅ |
|
||
| **自动分配策略** | - | ✅ 基础 | ✅ 高级 | ✅ 高级 |
|
||
| **自动化规则** | - | ✅ | ✅ | ✅ |
|
||
| **批量操作** | - | ✅ | ✅ | ✅ |
|
||
| **高级报表/洞察** | - | ✅ | ✅ | ✅ |
|
||
| **实时报表** | - | ✅ | ✅ | ✅ |
|
||
| **Platform API/Partner** | - | - | - | ✅ |
|
||
| **私有部署支持** | - | - | ✅ 基础 | ✅ 专属 |
|
||
| **定制开发** | - | - | - | ✅ |
|
||
|
||
### 2.4 计费模型设计
|
||
|
||
#### 计费维度
|
||
|
||
1. **坐席数(Agent)**:主计费单位,按月/年订阅
|
||
- 月付:标准价格
|
||
- 年付:8折优惠
|
||
|
||
2. **用量加价(Overage)**:
|
||
- 对话量超限:每 1K 对话 ¥10
|
||
- AI 调用量超限:每 1K 次 ¥5
|
||
- 存储超限:每 GB ¥2/月
|
||
|
||
3. **附加功能包(Add-on)**:
|
||
- CaptainAI 增强包:¥50/坐席/月(更高 AI 调用额度)
|
||
- 语音通话包:¥30/坐席/月 + Twilio 话费
|
||
- SSO 增强包:¥20/坐席/月(支持 OIDC + LDAP + SAML)
|
||
|
||
#### 数据模型设计
|
||
|
||
```go
|
||
// Subscription 订阅模型
|
||
type Subscription struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
Plan string `gorm:"not null;type:varchar(20)"` // community/professional/enterprise/ultimate
|
||
BillingCycle string `gorm:"not null;type:varchar(10)"` // monthly/yearly
|
||
AgentCount int `gorm:"not null;default:5"`
|
||
StartedAt time.Time `gorm:"not null"`
|
||
ExpiresAt time.Time `gorm:"not null"`
|
||
Status string `gorm:"not null;type:varchar(20)"` // active/expired/cancelled/suspended
|
||
AutoRenew bool `gorm:"default:true"`
|
||
Addons json.RawMessage `gorm:"type:jsonb"` // [{name, quantity, unit_price}]
|
||
OverageAlert bool `gorm:"default:true"` // 用量超限是否告警
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// BillingUsage 计费用量
|
||
type BillingUsage struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
Period string `gorm:"not null;type:varchar(7)"` // 2026-05
|
||
Conversations int `gorm:"default:0"`
|
||
AICalls int `gorm:"default:0"`
|
||
StorageGB float64 `gorm:"default:0"`
|
||
VoiceMinutes float64 `gorm:"default:0"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|
||
|
||
// FeatureEntitlement 功能授权
|
||
type FeatureEntitlement struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;uniqueIndex"`
|
||
Plan string `gorm:"not null"`
|
||
Features json.RawMessage `gorm:"type:jsonb"` // {"sla": true, "sso": true, "voice": true, ...}
|
||
MaxInboxes int `gorm:"default:5"`
|
||
MaxAgents int `gorm:"default:5"`
|
||
AICallLimit int `gorm:"default:0"` // 月度 AI 调用上限
|
||
StorageLimitGB float64 `gorm:"default:5"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|
||
```
|
||
|
||
### 2.5 功能开关中间件
|
||
|
||
```go
|
||
// FeatureGate 中间件:根据订阅计划控制功能访问
|
||
func FeatureGate(requiredFeature string) gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
accountID := getAccountID(c)
|
||
entitlement := getFeatureEntitlement(accountID)
|
||
|
||
features := parseFeatures(entitlement.Features)
|
||
if !features[requiredFeature] {
|
||
c.JSON(403, gin.H{
|
||
"error": "Feature not available in your plan",
|
||
"feature": requiredFeature,
|
||
"plan": entitlement.Plan,
|
||
"upgrade_url": "/billing/upgrade",
|
||
})
|
||
c.Abort()
|
||
return
|
||
}
|
||
c.Next()
|
||
}
|
||
}
|
||
|
||
// 路由注册示例
|
||
router.POST("/api/v1/accounts/:id/sla_policies",
|
||
FeatureGate("sla"), // Enterprise 专属
|
||
authMiddleware(),
|
||
slaHandler.Create(),
|
||
)
|
||
router.POST("/api/v1/accounts/:id/captain/assistants",
|
||
FeatureGate("captain_ai"), // Enterprise 专属
|
||
authMiddleware(),
|
||
captainHandler.Create(),
|
||
)
|
||
```
|
||
|
||
### 2.6 GoChat vs Chatwoot 商业模式差异
|
||
|
||
| 维度 | Chatwoot | GoChat 设计 |
|
||
|------|----------|-------------|
|
||
| **定价模型** | 按坐席/月(美元) | 按坐席/月(人民币优先,支持多币种) |
|
||
| **自部署** | 免费社区版 + 企业版需购买 license | Community 免费 + Enterprise 自部署可购买 license 密钥 |
|
||
| **功能授权** | features.yml + InstallationConfig | config.yaml + FeatureEntitlement DB + FeatureGate 中间件 |
|
||
| **AI 计费** | 无独立计费(含在 Enterprise) | CaptainAI 独立 Add-on 包 + 用量计费 |
|
||
| **语音计费** | 含在 Enterprise | 独立 Add-on + Twilio 话费透明 |
|
||
| **开放策略** | 企业版源码闭源 | 全源码开放 + license 密钥解锁企业功能 |
|
||
|
||
---
|
||
|
||
## 三、CaptainAI 功能设计
|
||
|
||
### 3.1 Captain AI 架构概览
|
||
|
||
Captain AI 是 GoChat 企业版的 AI 助手系统,提供两大核心能力:
|
||
|
||
1. **Captain(船长)**:AI 自动回复引擎,可绑定 Inbox 后自动处理客户咨询
|
||
2. **Copilot(副驾驶)**:AI 辅助工具,帮助坐席更快回复(建议回复、摘要、翻译)
|
||
|
||
### 3.2 功能模块拆解
|
||
|
||
| # | 子模块 | Chatwoot 对应 | 功能描述 | GoChat 实现状态 |
|
||
|---|--------|--------------|----------|-----------------|
|
||
| 1 | CaptainAssistant | Captain::Assistant | AI 助手 CRUD + Playground | ✅ 已实现 |
|
||
| 2 | CaptainDocument | Captain::Document | 知识库文档管理 | ✅ 已实现 |
|
||
| 3 | CaptainScenario | Captain::Scenario | 场景化对话流程 | ✅ 已实现 |
|
||
| 4 | CaptainCustomTool | Captain::CustomTool | 自定义 AI 工具 | ✅ 已实现 |
|
||
| 5 | CopilotSuggest | Copilot::SuggestReplies | 建议回复 | ✅ 已实现 |
|
||
| 6 | CopilotSummarize | Copilot::Summarize | 对话摘要 | ✅ 已实现 |
|
||
| 7 | CopilotTranslate | Copilot::Translate | 多语言翻译 | ✅ 已实现 |
|
||
| 8 | CaptainInbox | CaptainInbox | 助手-Inbox 绑定 | ✅ 已实现 |
|
||
| 9 | Playground | AssistantChatService/AgentRunnerService | 在线调试 | ✅ 已实现 |
|
||
| 10 | DocumentSearch | pgvector 向量检索 | 知识库搜索 | ✅ 已实现 |
|
||
|
||
### 3.3 CaptainAI 增强设计(超越 Chatwoot)
|
||
|
||
#### 3.3.1 多 LLM Provider 支持
|
||
|
||
Chatwoot 仅支持 OpenAI。GoChat 设计为多 Provider 架构:
|
||
|
||
```go
|
||
// LLMProvider 接口
|
||
type LLMProvider interface {
|
||
ChatCompletion(ctx context.Context, req ChatRequest) (ChatResponse, error)
|
||
Embedding(ctx context.Context, text string) ([]float32, error)
|
||
StreamChat(ctx context.Context, req ChatRequest) (<-chan ChatChunk, error)
|
||
}
|
||
|
||
// 支持的 Provider
|
||
var Providers = map[string]LLMProvider{
|
||
"openai": &OpenAIProvider{},
|
||
"azure": &AzureOpenAIProvider{},
|
||
"anthropic": &AnthropicProvider{}, // Claude
|
||
"deepseek": &DeepSeekProvider{}, // DeepSeek
|
||
"qwen": &QwenProvider{}, // 通义千问
|
||
"glm": &GLMProvider{}, // 智谱 GLM
|
||
"local": &LocalProvider{}, // llama.cpp 本地
|
||
"ollama": &OllamaProvider{}, // Ollama 本地
|
||
}
|
||
```
|
||
|
||
#### 3.3.2 RAG 知识库增强
|
||
|
||
| 特性 | Chatwoot | GoChat 增强 |
|
||
|------|----------|-------------|
|
||
| 向量存储 | pgvector 单一 | pgvector + Elasticsearch + Milvus 可选 |
|
||
| 文档类型 | 知识库文档 | + 网页抓取 + PDF + FAQ 自动提取 |
|
||
| 检索策略 | 简单向量相似度 | 混合检索(向量 + 关键词 + 重排序) |
|
||
| 上下文窗口 | 固定 | 动态窗口 + MMR 去重 |
|
||
| 多语言支持 | 英文为主 | 中英双语 + 自动检测 |
|
||
|
||
#### 3.3.3 Agent Tool 框架
|
||
|
||
GoChat Agent Tool 设计超越 Chatwoot 的简单工具列表:
|
||
|
||
```go
|
||
// AgentTool 接口
|
||
type AgentTool interface {
|
||
Name() string
|
||
Description() string
|
||
Parameters() ToolParameters // JSON Schema
|
||
Execute(ctx context.Context, args map[string]interface{}) (ToolResult, error)
|
||
}
|
||
|
||
// 内置工具
|
||
type FAQTool struct{} // FAQ 检索
|
||
type MemoryTool struct{} // 对话记忆
|
||
type ContactAttributesTool struct{} // 客户属性查询
|
||
type OrderStatusTool struct{} // 订单状态查询(需企业定制)
|
||
type KnowledgeBaseTool struct{} // 知识库检索
|
||
|
||
// 自定义工具注册表
|
||
type ToolRegistry struct {
|
||
builtin map[string]AgentTool
|
||
custom map[string]AgentTool // 用户通过 API 注册
|
||
}
|
||
|
||
// Agent Runner(v2 引擎)
|
||
type AgentRunnerService struct {
|
||
provider LLMProvider
|
||
registry *ToolRegistry
|
||
assistant *CaptainAssistant
|
||
documents []CaptainDocument
|
||
}
|
||
|
||
func (s *AgentRunnerService) Run(ctx context.Context, message string) (*AgentResponse, error) {
|
||
// 1. 构建系统 prompt(assistant config + response_guidelines + guardrails)
|
||
// 2. 检索相关文档(RAG)
|
||
// 3. 调用 LLM(带 tool_choice)
|
||
// 4. LLM 返回 tool_call → 执行工具 → 回注结果
|
||
// 5. 循环直到 LLM 返回最终回复
|
||
// 6. 返回回复 + 引用来源 + 工具调用日志
|
||
}
|
||
```
|
||
|
||
#### 3.3.4 Copilot 增强功能
|
||
|
||
| 增强功能 | 描述 | 优先级 |
|
||
|----------|------|--------|
|
||
| **情绪分析** | 分析客户情绪(正面/负面/中性),帮助坐席判断应对策略 | P1 |
|
||
| **意图识别** | 自动识别客户意图(投诉/咨询/退换/续费等) | P1 |
|
||
| **智能摘要** | 不仅摘要对话,还提取关键决策点和承诺 | P0 |
|
||
| **知识推荐** | 根据对话上下文推荐相关知识库文档 | P1 |
|
||
| **多轮建议** | 不仅建议单条回复,还提供后续跟进建议 | P2 |
|
||
| **质检辅助** | 对话结束后自动标注质检项(合规/违规) | P2 |
|
||
|
||
### 3.4 CaptainAI API 设计
|
||
|
||
```
|
||
# Captain Assistant CRUD
|
||
GET /api/v1/accounts/{id}/captain/assistants # 列表
|
||
POST /api/v1/accounts/{id}/captain/assistants # 创建
|
||
GET /api/v1/accounts/{id}/captain/assistants/{aid} # 详情
|
||
PATCH /api/v1/accounts/{id}/captain/assistants/{aid} # 更新
|
||
DELETE /api/v1/accounts/{id}/captain/assistants/{aid} # 删除
|
||
|
||
# Playground
|
||
POST /api/v1/accounts/{id}/captain/assistants/{aid}/playground # 调试
|
||
|
||
# Tools
|
||
GET /api/v1/accounts/{id}/captain/assistants/tools # 可用工具列表
|
||
|
||
# Inbox Binding
|
||
POST /api/v1/accounts/{id}/captain/assistants/{aid}/inboxes # 绑定
|
||
DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/inboxes/{inbox_id} # 解绑
|
||
|
||
# Captain Document CRUD
|
||
GET /api/v1/accounts/{id}/captain/assistants/{aid}/documents
|
||
POST /api/v1/accounts/{id}/captain/assistants/{aid}/documents
|
||
DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/documents/{did}
|
||
|
||
# Captain Scenario CRUD
|
||
GET /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios
|
||
POST /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios
|
||
PATCH /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios/{sid}
|
||
DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios/{sid}
|
||
|
||
# Copilot
|
||
POST /api/v1/accounts/{id}/copilot/suggest_replies # 建议回复
|
||
POST /api/v1/accounts/{id}/copilot/summarize # 对话摘要
|
||
POST /api/v1/accounts/{id}/copilot/translate # 翻译
|
||
POST /api/v1/accounts/{id}/copilot/analyze_sentiment # 情绪分析(新增)
|
||
POST /api/v1/accounts/{id}/copilot/detect_intent # 意图识别(新增)
|
||
```
|
||
|
||
### 3.5 数据模型
|
||
|
||
```go
|
||
// CaptainAssistant — AI 助手
|
||
type CaptainAssistant struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
Name string `gorm:"not null;type:varchar(255)"`
|
||
Description string `gorm:"type:text"`
|
||
Status AssistantStatus `gorm:"type:varchar(20);default:'draft'"` // active/draft/archived
|
||
Config json.RawMessage `gorm:"type:jsonb"` // {temperature, feature_faq, feature_memory, ...}
|
||
Guardrails json.RawMessage `gorm:"type:jsonb"` // 限制性规则
|
||
ResponseGuidelines json.RawMessage `gorm:"type:jsonb"` // 回复指导方针
|
||
LLMProvider string `gorm:"type:varchar(50);default:'openai'"` // 新增:LLM Provider
|
||
LLMModel string `gorm:"type:varchar(100);default:'gpt-4'"` // 新增:具体模型
|
||
MaxTokens int `gorm:"default:2048"` // 新增:最大 token
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// CaptainDocument — 知识库文档
|
||
type CaptainDocument struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
AssistantID uint `gorm:"not null;index"`
|
||
ExternalURL string `gorm:"type:varchar(500)"` // 外部链接
|
||
Content string `gorm:"type:text"` // 文档内容
|
||
Embedding []float32 `gorm:"type:vector(1536)"` // pgvector
|
||
SourceType string `gorm:"type:varchar(20)"` // url/file/faq/api
|
||
Status string `gorm:"type:varchar(20);default:'active'"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// CaptainScenario — 对话场景
|
||
type CaptainScenario struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
AssistantID uint `gorm:"not null;index"`
|
||
Name string `gorm:"not null;type:varchar(255)"`
|
||
Description string `gorm:"type:text"`
|
||
TriggerRules json.RawMessage `gorm:"type:jsonb"` // 触发条件
|
||
FlowConfig json.RawMessage `gorm:"type:jsonb"` // 场景流程配置
|
||
Priority int `gorm:"default:0"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// CaptainCustomTool — 自定义工具
|
||
type CaptainCustomTool struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
AssistantID uint `gorm:"not null;index"`
|
||
Name string `gorm:"not null;type:varchar(100)"`
|
||
Description string `gorm:"type:text"`
|
||
Parameters json.RawMessage `gorm:"type:jsonb"` // JSON Schema
|
||
Endpoint string `gorm:"type:varchar(500)"` // API endpoint
|
||
Method string `gorm:"type:varchar(10);default:'POST'"`
|
||
Headers json.RawMessage `gorm:"type:jsonb"`
|
||
AuthType string `gorm:"type:varchar(20)"` // none/bearer/basic/oauth2
|
||
AuthConfig json.RawMessage `gorm:"type:jsonb"`
|
||
Status string `gorm:"type:varchar(20);default:'active'"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// CaptainInbox — 助手-Inbox 绑定
|
||
type CaptainInbox struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
AssistantID uint `gorm:"not null;index"`
|
||
InboxID uint `gorm:"not null;index"`
|
||
CreatedAt time.Time
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、SSO 单点登录设计
|
||
|
||
### 4.1 SSO 架构概览
|
||
|
||
GoChat 企业版 SSO 支持 **三种协议**,超越 Chatwoot 仅支持 SAML:
|
||
|
||
| 协议 | Chatwoot | GoChat | 适用场景 |
|
||
|------|----------|--------|----------|
|
||
| **SAML 2.0** | ✅ 仅此一种 | ✅ | Okta、Azure AD、OneLogin |
|
||
| **OIDC (OAuth 2.0)** | ❌ | ✅ 新增 | Google Workspace、Auth0、Keycloak |
|
||
| **LDAP** | ❌ | ✅ 新增 | 传统企业 AD/LDAP |
|
||
|
||
### 4.2 SAML 2.0 设计
|
||
|
||
#### 数据模型
|
||
|
||
```go
|
||
// AccountSamlSettings — SAML 配置
|
||
type AccountSamlSettings struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;uniqueIndex"`
|
||
SsoURL string `gorm:"not null;type:varchar(500)"` // IdP SSO URL
|
||
Certificate string `gorm:"not null;type:text"` // X509 证书
|
||
IdpEntityID string `gorm:"not null;type:varchar(500)"` // IdP Entity ID
|
||
SpEntityID string `gorm:"type:varchar(500)"` // 自动生成 SP Entity ID
|
||
RoleMappings json.RawMessage `gorm:"type:jsonb"` // SAML 属性 → GoChat 角色
|
||
SamlVersion string `gorm:"type:varchar(10);default:'2.0'"`
|
||
NameIDFormat string `gorm:"type:varchar(50);default:'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'"`
|
||
SignAssertions bool `gorm:"default:true"`
|
||
SignRequests bool `gorm:"default:false"`
|
||
EncryptAssertions bool `gorm:"default:false"`
|
||
ForceAuthn bool `gorm:"default:false"` // 强制重新认证
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
```
|
||
|
||
#### SAML 认证流程
|
||
|
||
```
|
||
1. 用户点击 "SSO Login" → GoChat 生成 SAML AuthnRequest
|
||
2. 重定向到 IdP SsoURL(Okta/Azure AD 等)
|
||
3. 用户在 IdP 完成认证
|
||
4. IdP 返回 SAML Response → GoChat ACS URL (/api/v1/saml/callback)
|
||
5. GoChat 验证 SAML Response:
|
||
a. 验证签名(使用 Certificate)
|
||
b. 验证时间戳(NotOnOrAfter)
|
||
c. 验证 Audience(SpEntityID)
|
||
d. 提取 NameID(email)
|
||
6. SamlUserBuilder 处理:
|
||
a. 按 email 查找已有用户 → 如属于账户直接登录
|
||
b. 新用户 → 创建 + 设置 provider='saml' + 自动确认邮箱
|
||
c. 角色映射 → 根据 RoleMappings 配置分配 AccountUser 角色
|
||
7. 返回 JWT token → 完成登录
|
||
```
|
||
|
||
#### API 端点
|
||
|
||
```
|
||
# SAML 配置管理
|
||
GET /api/v1/accounts/{id}/saml_settings # 获取配置
|
||
POST /api/v1/accounts/{id}/saml_settings # 创建配置
|
||
PUT /api/v1/accounts/{id}/saml_settings # 更新配置
|
||
DELETE /api/v1/accounts/{id}/saml_settings # 删除配置
|
||
|
||
# SAML 认证流程
|
||
GET /api/v1/accounts/{id}/saml/authn_request # 生成 AuthnRequest + 重定向
|
||
POST /api/v1/saml/callback # ACS 回调处理
|
||
GET /api/v1/accounts/{id}/saml/metadata # SP Metadata(供 IdP 配置)
|
||
GET /api/v1/accounts/{id}/saml/certificate_fingerprint # 证书指纹
|
||
```
|
||
|
||
### 4.3 OIDC (OpenID Connect) 设计
|
||
|
||
```go
|
||
// AccountOIDCSettings — OIDC 配置(新增)
|
||
type AccountOIDCSettings struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;uniqueIndex"`
|
||
IssuerURL string `gorm:"not null;type:varchar(500)"` // OIDC Issuer URL
|
||
ClientID string `gorm:"not null;type:varchar(200)"`
|
||
ClientSecret string `gorm:"not null;type:varchar(200)"`
|
||
Scopes string `gorm:"type:varchar(200);default:'openid,email,profile'"`
|
||
AuthorizationURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现
|
||
TokenURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现
|
||
JWKSURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现
|
||
UserInfoURL string `gorm:"type:varchar(500)"`
|
||
RoleClaim string `gorm:"type:varchar(100);default:'roles'"` // 角色声明字段
|
||
GroupClaim string `gorm:"type:varchar(100);default:'groups'"` // 组声明字段
|
||
AutoProvision bool `gorm:"default:true"` // 自动创建新用户
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
```
|
||
|
||
#### OIDC 认证流程
|
||
|
||
```
|
||
1. 用户点击 "OIDC Login" → 重定向到 AuthorizationURL
|
||
2. IdP 认证 → 返回 authorization_code
|
||
3. GoChat 交换 code → TokenURL 获取 access_token + id_token
|
||
4. 验证 id_token(JWKS) → 提取 claims(email, name, roles)
|
||
5. OIDCUserBuilder 处理(类似 SamlUserBuilder)
|
||
6. 返回 JWT token → 完成登录
|
||
```
|
||
|
||
#### API 端点
|
||
|
||
```
|
||
GET /api/v1/accounts/{id}/oidc_settings # 获取配置
|
||
POST /api/v1/accounts/{id}/oidc_settings # 创建配置
|
||
PUT /api/v1/accounts/{id}/oidc_settings # 更新配置
|
||
DELETE /api/v1/accounts/{id}/oidc_settings # 删除配置
|
||
GET /api/v1/accounts/{id}/oidc/authorize # 发起 OIDC 认证
|
||
POST /api/v1/oidc/callback # OIDC 回调
|
||
```
|
||
|
||
### 4.4 LDAP 设计
|
||
|
||
```go
|
||
// AccountLDAPSettings — LDAP 配置(新增)
|
||
type AccountLDAPSettings struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;uniqueIndex"`
|
||
Host string `gorm:"not null;type:varchar(200)"` // LDAP 服务器
|
||
Port int `gorm:"not null;default:389"`
|
||
UseTLS bool `gorm:"default:false"`
|
||
BaseDN string `gorm:"not null;type:varchar(200)"` // 搜索基准 DN
|
||
BindDN string `gorm:"type:varchar(200)"` // 绑定 DN
|
||
BindPassword string `gorm:"type:varchar(200)"` // 绑定密码
|
||
UserFilter string `gorm:"type:varchar(200);default:'(objectClass=person)'"`
|
||
EmailAttribute string `gorm:"type:varchar(50);default:'mail'"`
|
||
NameAttribute string `gorm:"type:varchar(50);default:'cn'"`
|
||
GroupAttribute string `gorm:"type:varchar(50);default:'memberOf'"`
|
||
RoleMappings json.RawMessage `gorm:"type:jsonb"` // LDAP group → GoChat 角色
|
||
AutoProvision bool `gorm:"default:true"`
|
||
SyncInterval int `gorm:"default:3600"` // 同步间隔(秒)
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
```
|
||
|
||
#### LDAP 认证流程
|
||
|
||
```
|
||
1. 用户输入企业账号密码 → GoChat 发起 LDAP Bind
|
||
2. BindDN + BindPassword 连接 LDAP 服务器
|
||
3. 搜索 BaseDN + UserFilter → 获取用户 DN
|
||
4. 用户 DN + 密码验证(Bind 验证)
|
||
5. 提取 email/name/groups 属性
|
||
6. LDAPUserBuilder 处理(类似 SamlUserBuilder)
|
||
7. 返回 JWT token → 完成登录
|
||
8. 后台定时同步 LDAP 组 → GoChat 角色
|
||
```
|
||
|
||
### 4.5 SSO 中间件设计
|
||
|
||
```go
|
||
// SSOMiddleware — SSO 通用中间件
|
||
func SSOMiddleware() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
accountID := getAccountID(c)
|
||
|
||
// 检查账户是否配置了 SSO
|
||
samlSettings := getSamlSettings(accountID)
|
||
oidcSettings := getOIDCSettings(accountID)
|
||
ldapSettings := getLDAPSettings(accountID)
|
||
|
||
if samlSettings != nil || oidcSettings != nil || ldapSettings != nil {
|
||
// 强制 SSO 登录(禁用普通邮箱登录)
|
||
// 仅管理员可绕过 SSO(super_admin bypass)
|
||
if !isSuperAdmin(c) {
|
||
enforceSSO(c)
|
||
}
|
||
}
|
||
c.Next()
|
||
}
|
||
}
|
||
|
||
// SSOProviderRouter — 根据配置路由到不同 SSO Provider
|
||
func SSOProviderRouter(accountID uint) string {
|
||
if getSamlSettings(accountID) != nil { return "saml" }
|
||
if getOIDCSettings(accountID) != nil { return "oidc" }
|
||
if getLDAPSettings(accountID) != nil { return "ldap" }
|
||
return "email" // 默认邮箱登录
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 五、语音通话功能设计
|
||
|
||
### 5.1 语音通话架构概览
|
||
|
||
GoChat 语音通话采用 **Conference 模式**(坐席 + 客户通过会议桥连接),与 Chatwoot 保持一致,但增加更多 Provider 支持:
|
||
|
||
| Provider | Chatwoot | GoChat | 说明 |
|
||
|----------|----------|--------|------|
|
||
| **Twilio** | ✅ | ✅ | 主要语音 Provider |
|
||
| **WhatsApp 通话** | ✅ | ✅ | WhatsApp Voice Call |
|
||
| **Agora(声网)** | ❌ | ✅ 新增 | 国内音视频首选 |
|
||
| **Tencent RTC** | ❌ | ✅ 新增 | 腾讯实时音视频 |
|
||
|
||
### 5.2 数据模型
|
||
|
||
```go
|
||
// Call — 通话记录
|
||
type Call struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
AccountID uint `gorm:"not null;index"`
|
||
InboxID uint `gorm:"not null;index"`
|
||
ConversationID uint `gorm:"not null;index"`
|
||
ContactID uint `gorm:"not null"`
|
||
AgentID uint `gorm:"index"` // 接听坐席
|
||
|
||
CallSource string `gorm:"not null;type:varchar(20)"` // inbox/initiated
|
||
CallDirection string `gorm:"not null;type:varchar(20)"` // inbound/outbound
|
||
Status string `gorm:"not null;type:varchar(20)"` // ringing/in_progress/completed/no_answer/failed/busy
|
||
|
||
Provider string `gorm:"type:varchar(20);default:'twilio'"` // twilio/agora/tencent/whatsapp
|
||
CallSID string `gorm:"type:varchar(100)"` // Provider 侧通话 ID
|
||
ConferenceSID string `gorm:"type:varchar(100)"` // Conference SID(Twilio)
|
||
|
||
DurationSeconds int `gorm:"default:0"` // 通话时长
|
||
RecordingURL string `gorm:"type:varchar(500)"` // 录音 URL
|
||
RecordingSID string `gorm:"type:varchar(100)"` // 录音 SID
|
||
Transcript string `gorm:"type:text"` // 通话转录
|
||
|
||
VoipToken string `gorm:"type:varchar(500)"` // Twilio Access Token
|
||
ClientIdentity string `gorm:"type:varchar(100)"` // Client 标识
|
||
|
||
AdditionalAttrs json.RawMessage `gorm:"type:jsonb"` // 附加属性
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
}
|
||
|
||
// CallStatus 状态机
|
||
// ringing → in_progress → completed
|
||
// ringing → no_answer
|
||
// ringing → failed
|
||
// ringing → busy
|
||
// in_progress → completed(正常结束)
|
||
```
|
||
|
||
### 5.3 通话流程设计
|
||
|
||
#### 5.3.1 呼出通话(Outbound)
|
||
|
||
```
|
||
1. 坐席在对话页面点击 "Call" 按钮
|
||
2. GoChat 创建 Call 记录(status=ringing, direction=outbound)
|
||
3. 生成 VoipToken(Twilio Access Token + VoiceGrant)
|
||
4. 前端使用 Twilio Client SDK 发起通话
|
||
5. 同时通过 Twilio API 呼叫客户号码
|
||
6. Twilio Conference 模式:坐席 + 客户加入会议桥
|
||
7. 客户接听 → status=in_progress + 自动分配坐席到对话
|
||
8. 通话结束 → status=completed + 更新 duration_seconds
|
||
9. 对话中插入 voice_call 消息气泡(含通话详情)
|
||
```
|
||
|
||
#### 5.3.2 呼入通话(Inbound)
|
||
|
||
```
|
||
1. 客户拨打企业号码 → Twilio 转发到 GoChat Webhook
|
||
2. GoChat Voice::IncomingCallService 处理:
|
||
a. 查找关联 Inbox + Contact
|
||
b. 创建/查找 Conversation
|
||
c. 创建 Call(status=ringing, direction=inbound)
|
||
d. 通知坐席(WebSocket 推送 + 呼叫响铃)
|
||
3. 坐席接听 → claim_call + auto_assign
|
||
4. 通话进行 → status=in_progress
|
||
5. 通话结束 → status=completed + 录音处理
|
||
```
|
||
|
||
#### 5.3.3 WhatsApp 通话
|
||
|
||
```
|
||
1. WhatsApp 客户发起通话请求 → GoChat Webhook 接收 SDP offer
|
||
2. CallPermissionReplyService 处理权限判断
|
||
3. 呼入通话创建 → 通知坐席
|
||
4. 坐席 accept/reject → WhatsApp SDP answer/reject
|
||
5. 通话进行 → 状态更新
|
||
```
|
||
|
||
### 5.4 通话 Provider 抽象层
|
||
|
||
```go
|
||
// VoiceProvider 接口
|
||
type VoiceProvider interface {
|
||
// 基础通话
|
||
MakeCall(ctx context.Context, params MakeCallParams) (*CallResult, error)
|
||
HangupCall(ctx context.Context, callSID string) error
|
||
|
||
// Conference
|
||
CreateConference(ctx context.Context, params ConferenceParams) (*ConferenceResult, error)
|
||
EndConference(ctx context.Context, conferenceSID string) error
|
||
|
||
// Token
|
||
GenerateToken(ctx context.Context, identity string) (string, error)
|
||
|
||
// 录音
|
||
StartRecording(ctx context.Context, callSID string) error
|
||
StopRecording(ctx context.Context, callSID string) error
|
||
GetRecordingURL(ctx context.Context, recordingSID string) (string, error)
|
||
|
||
// Webhook 处理
|
||
HandleIncomingCall(ctx context.Context, payload map[string]interface{}) (*IncomingCallResult, error)
|
||
HandleConferenceEvent(ctx context.Context, event ConferenceEvent) error
|
||
HandleRecordingStatus(ctx context.Context, payload map[string]interface{}) error
|
||
}
|
||
|
||
// Twilio Provider 实现
|
||
type TwilioProvider struct {
|
||
AccountSID string
|
||
AuthToken string
|
||
AppSID string
|
||
PhoneNumber string
|
||
APIBase string // https://api.twilio.com
|
||
}
|
||
|
||
// Agora Provider 实现(新增)
|
||
type AgoraProvider struct {
|
||
AppID string
|
||
AppCertificate string
|
||
APIBase string
|
||
}
|
||
|
||
// TencentRTC Provider 实现(新增)
|
||
type TencentRTCProvider struct {
|
||
SDKAppID int
|
||
SecretKey string
|
||
APIBase string
|
||
}
|
||
```
|
||
|
||
### 5.5 通话 API 设计
|
||
|
||
```
|
||
# 通话管理
|
||
POST /api/v1/accounts/{id}/calls # 创建通话(呼出)
|
||
GET /api/v1/accounts/{id}/calls/{call_id} # 通话详情
|
||
PUT /api/v1/accounts/{id}/calls/{call_id} # 更新通话状态
|
||
DELETE /api/v1/accounts/{id}/calls/{call_id} # 结束通话
|
||
|
||
# 通话动作
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/answer # 接听
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/hangup # 挂断
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/reject # 拒接
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/mute # 静音
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/unmute # 取消静音
|
||
|
||
# Twilio Token
|
||
GET /api/v1/accounts/{id}/voice/token # 获取 VoIP Token
|
||
|
||
# 录音
|
||
POST /api/v1/accounts/{id}/calls/{call_id}/record # 开始录音
|
||
GET /api/v1/accounts/{id}/calls/{call_id}/recording # 获取录音
|
||
|
||
# Webhook(Twilio 回调)
|
||
POST /voice/twilio/incoming # Twilio 呼入回调
|
||
POST /voice/twilio/conference # Twilio 会议事件
|
||
POST /voice/twilio/recording_status # Twilio 录音状态
|
||
|
||
# WhatsApp 通话
|
||
POST /api/v1/accounts/{id}/whatsapp/call/accept # 接听 WhatsApp 通话
|
||
POST /api/v1/accounts/{id}/whatsapp/call/reject # 拒绝 WhatsApp 通话
|
||
```
|
||
|
||
### 5.6 录音与转录设计
|
||
|
||
```go
|
||
// VoiceRecordingService — 录音处理
|
||
type VoiceRecordingService struct {
|
||
provider VoiceProvider
|
||
storage StorageProvider // 本地/S3/OSS
|
||
}
|
||
|
||
func (s *VoiceRecordingService) ProcessRecording(ctx context.Context, callID uint) error {
|
||
// 1. 从 Provider 获取录音文件 URL
|
||
// 2. 下载录音文件
|
||
// 3. 存储到对象存储(S3/OSS)
|
||
// 4. 创建 Attachment 关联到对话消息
|
||
// 5. 可选:调用转录服务(Whisper/阿里语音识别)
|
||
// 6. 更新 Call.RecordingURL + Call.Transcript
|
||
}
|
||
|
||
// VoiceTranscriptionService — 通话转录
|
||
type VoiceTranscriptionService interface {
|
||
Transcribe(ctx context.Context, audioURL string) (TranscriptionResult, error)
|
||
}
|
||
|
||
// 支持的转录 Provider
|
||
var TranscriptionProviders = map[string]VoiceTranscriptionService{
|
||
"whisper": &WhisperProvider{}, // OpenAI Whisper
|
||
"aliyun": &AliyunASRProvider{}, // 阿里云语音识别
|
||
"tencent": &TencentASRProvider{}, // 腾讯云语音识别
|
||
"azure": &AzureSpeechProvider{}, // Azure Speech
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、企业版功能实施路线图
|
||
|
||
### 6.1 Phase 分期
|
||
|
||
| Phase | 功能 | 优先级 | 预估工时 | 前置条件 |
|
||
|-------|------|--------|----------|----------|
|
||
| **E1** | Feature Gate + Subscription 模型 | P0 | 3天 | 无 |
|
||
| **E2** | SAML SSO 完整实现 | P0 | 5天 | E1 |
|
||
| **E3** | OIDC SSO 实现 | P1 | 4天 | E2 |
|
||
| **E4** | LDAP SSO 实现 | P2 | 4天 | E2 |
|
||
| **E5** | SLA 策略完整实现 | P0 | 4天 | E1 |
|
||
| **E6** | 审计日志实现 | P0 | 3天 | E1 |
|
||
| **E7** | 自定义角色权限 | P0 | 5天 | E1 |
|
||
| **E8** | 语音通话(Twilio) | P1 | 7天 | E1 |
|
||
| **E9** | 语音通话(Agora/Tencent) | P2 | 4天 | E8 |
|
||
| **E10** | CaptainAI 增强(多 LLM) | P1 | 5天 | E1 |
|
||
| **E11** | Copilot 增强 | P2 | 3天 | E10 |
|
||
| **E12** | 坐席容量策略 | P1 | 3天 | E7 |
|
||
| **E13** | 公司/组织管理完善 | P1 | 3天 | E7 |
|
||
| **E14** | 定时任务调度 | P2 | 2天 | Worker Pool 可用 |
|
||
| **E15** | AgentBot 完善 | P1 | 4天 | E1 |
|
||
|
||
### 6.2 E1 Feature Gate 实现细节
|
||
|
||
```
|
||
E1 是所有企业功能的基石,需要优先实现:
|
||
|
||
1. 数据模型:Subscription + BillingUsage + FeatureEntitlement
|
||
2. 中间件:FeatureGate(requiredFeature) → 403 if not entitled
|
||
3. 路由注册:所有企业版路由加 FeatureGate 中间件
|
||
4. 配置管理:config.yaml 增加 billing section
|
||
5. License 密钥验证(自部署场景)
|
||
6. API:
|
||
- GET /api/v1/accounts/{id}/subscription # 查看订阅
|
||
- POST /api/v1/accounts/{id}/subscription # 创建/更新订阅
|
||
- GET /api/v1/accounts/{id}/entitlement # 查看功能授权
|
||
- GET /api/v1/accounts/{id}/billing_usage # 查看用量
|
||
```
|
||
|
||
### 6.3 关键技术决策
|
||
|
||
| 决策点 | 选项 | 推荐 | 原因 |
|
||
|--------|------|------|------|
|
||
| **向量存储** | pgvector vs Milvus vs ES | pgvector(默认) + Milvus(可选) | pgvector 与 PG 一体化,运维简单 |
|
||
| **LLM 调用** | 直接 HTTP vs SDK | 直接 HTTP(resty/v2) | 减少依赖,多 Provider 更灵活 |
|
||
| **SSO 协议** | 仅 SAML vs 三协议 | 三协议(SAML+OIDC+LDAP) | 国内企业 OIDC/LDAP 更常见 |
|
||
| **语音 Provider** | 仅 Twilio vs 多 Provider | Twilio(海外) + Agora(国内) | 国内 Agaora 生态更成熟 |
|
||
| **计费存储** | Stripe vs 本地 | Stripe(海外) + 支付宝/微信(国内) | 双币种双渠道 |
|
||
| **功能授权** | config.yaml vs DB | DB(FeatureEntitlement) | 云版动态调整,自部署用 config.yaml + license |
|
||
| **录音转录** | Whisper vs 云 ASR | Whisper(本地) + 阿里 ASR(云) | 灵活选择 |
|
||
| **Conference 模式** | 保留 vs 简化 | 保留 Conference 模式 | 与 Chatwoot 一致,坐席可转接 |
|
||
|
||
---
|
||
|
||
## 附录A:Chatwoot 企业版 Feature Flag 对照表
|
||
|
||
| Flag | 功能 | GoChat 对应开关 |
|
||
|------|------|-----------------|
|
||
| `enterprise` | 企业版总开关 | `FeatureEntitlement.plan >= enterprise` |
|
||
| `saml` | SAML SSO | `FeatureEntitlement.features.sso_saml` |
|
||
| `voice` | 语音通话 | `FeatureEntitlement.features.voice` |
|
||
| `captain_ai` | Captain AI | `FeatureEntitlement.features.captain_ai` |
|
||
| `audit_log` | 审计日志 | `FeatureEntitlement.features.audit_log` |
|
||
| `custom_roles` | 自定义角色 | `FeatureEntitlement.features.custom_roles` |
|
||
| `sla` | SLA 策略 | `FeatureEntitlement.features.sla` |
|
||
| `agent_capacity` | 坐席容量 | `FeatureEntitlement.features.agent_capacity` |
|
||
|
||
## 附录B:GoChat 新增企业版功能 Flag(超越 Chatwoot)
|
||
|
||
| Flag | 功能 | 描述 |
|
||
|------|------|------|
|
||
| `oidc_sso` | OIDC SSO | OpenID Connect 单点登录(新增) |
|
||
| `ldap_sso` | LDAP SSO | LDAP 认证(新增) |
|
||
| `multi_llm` | 多 LLM Provider | 支持 Claude/DeepSeek/Qwen/GLM 等(新增) |
|
||
| `voice_agora` | Agora 语音 | 声网语音通话(新增) |
|
||
| `voice_tencent` | Tencent RTC | 腾讯实时音视频(新增) |
|
||
| `sentiment_analysis` | 情绪分析 | Copilot 情绪分析(新增) |
|
||
| `intent_detection` | 意图识别 | Copilot 意图识别(新增) |
|
||
| `voice_transcription` | 通话转录 | 通话自动转录(新增) |
|
||
| `hybrid_rag` | 混合 RAG | 向量+关键词混合检索(新增) |
|
||
|
||
---
|
||
|
||
> **文档维护说明**:本文档随 GoChat 企业版功能迭代持续更新。每次 Phase 完成后更新实施状态和差距分析。 |