Files
gochat/docs/ENTERPRISE_FEATURE_ANALYSIS.md
T
2026-06-04 15:44:48 +08:00

41 KiB
Raw Blame History

GoChat 企业功能分析文档

版本:v1.0
生成日期:2026-05-25
目标:Chatwoot 企业版功能深度分析 + GoChat 商业收费功能构思 + CaptainAI/SSO/语音通话等功能设计方案


目录

  1. Chatwoot 企业版功能全景分析
  2. GoChat 商业收费模式构思
  3. CaptainAI 功能设计
  4. 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 Flagfeatures.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

数据模型设计

// 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 功能开关中间件

// 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 架构:

// 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 的简单工具列表:

// 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 Runnerv2 引擎)
type AgentRunnerService struct {
    provider   LLMProvider
    registry   *ToolRegistry
    assistant  *CaptainAssistant
    documents  []CaptainDocument
}

func (s *AgentRunnerService) Run(ctx context.Context, message string) (*AgentResponse, error) {
    // 1. 构建系统 promptassistant 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 数据模型

// 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 设计

数据模型

// 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 SsoURLOkta/Azure AD 等)
3. 用户在 IdP 完成认证
4. IdP 返回 SAML Response → GoChat ACS URL (/api/v1/saml/callback)
5. GoChat 验证 SAML Response
   a. 验证签名(使用 Certificate
   b. 验证时间戳(NotOnOrAfter
   c. 验证 AudienceSpEntityID
   d. 提取 NameIDemail
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) 设计

// 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_tokenJWKS → 提取 claimsemail, 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 设计

// 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 中间件设计

// 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 登录(禁用普通邮箱登录)
            // 仅管理员可绕过 SSOsuper_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 数据模型

// 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 SIDTwilio
    
    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. 生成 VoipTokenTwilio 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. 创建 Callstatus=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 抽象层

// 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     # 获取录音

# WebhookTwilio 回调)
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 录音与转录设计

// 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 直接 HTTPresty/v2 减少依赖,多 Provider 更灵活
SSO 协议 仅 SAML vs 三协议 三协议(SAML+OIDC+LDAP 国内企业 OIDC/LDAP 更常见
语音 Provider 仅 Twilio vs 多 Provider Twilio(海外) + Agora(国内) 国内 Agaora 生态更成熟
计费存储 Stripe vs 本地 Stripe(海外) + 支付宝/微信(国内) 双币种双渠道
功能授权 config.yaml vs DB DBFeatureEntitlement 云版动态调整,自部署用 config.yaml + license
录音转录 Whisper vs 云 ASR Whisper(本地) + 阿里 ASR(云) 灵活选择
Conference 模式 保留 vs 简化 保留 Conference 模式 与 Chatwoot 一致,坐席可转接

附录AChatwoot 企业版 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

附录BGoChat 新增企业版功能 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 完成后更新实施状态和差距分析。