feat: Phase 5.1 - Client 扩展,添加 orchestrator 依赖
- 扩展 Client 结构体,添加 sessionManager、orchestrator、cancelFuncs 字段 - 创建 WSClient 适配器实现 orchestrator.Sender 接口 - 更新 ServeWS 函数签名,接收 orchestrator 参数 - 在 main.go 中初始化 AI 服务和 Orchestrator
This commit is contained in:
@@ -10,8 +10,12 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"github.com/hhs/camtalk/internal/ai/llm"
|
||||||
|
"github.com/hhs/camtalk/internal/ai/stt"
|
||||||
|
"github.com/hhs/camtalk/internal/ai/tts"
|
||||||
"github.com/hhs/camtalk/internal/config"
|
"github.com/hhs/camtalk/internal/config"
|
||||||
"github.com/hhs/camtalk/internal/logger"
|
"github.com/hhs/camtalk/internal/logger"
|
||||||
|
"github.com/hhs/camtalk/internal/orchestrator"
|
||||||
"github.com/hhs/camtalk/internal/session"
|
"github.com/hhs/camtalk/internal/session"
|
||||||
"github.com/hhs/camtalk/internal/ws"
|
"github.com/hhs/camtalk/internal/ws"
|
||||||
)
|
)
|
||||||
@@ -40,6 +44,14 @@ func main() {
|
|||||||
sessionMgr = session.NewMemoryManager(30*time.Minute, 20)
|
sessionMgr = session.NewMemoryManager(30*time.Minute, 20)
|
||||||
defer sessionMgr.(*session.MemoryManager).Stop()
|
defer sessionMgr.(*session.MemoryManager).Stop()
|
||||||
|
|
||||||
|
// 初始化 AI 服务
|
||||||
|
sttService := stt.NewDeepgramService(cfg.AI.STT.APIKey, cfg.AI.STT.Endpoint, logger.Log)
|
||||||
|
llmService := llm.NewOpenAIService(cfg.AI.LLM.APIKey, cfg.AI.LLM.Model, cfg.AI.LLM.Endpoint, cfg.AI.LLM.Timeout, logger.Log)
|
||||||
|
ttsService := tts.NewOpenAIService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Speed, cfg.AI.TTS.Timeout, logger.Log)
|
||||||
|
|
||||||
|
// 初始化 Orchestrator
|
||||||
|
orch := orchestrator.New(sttService, llmService, ttsService, sessionMgr)
|
||||||
|
|
||||||
// Gin 模式
|
// Gin 模式
|
||||||
if cfg.App.Env == "prod" {
|
if cfg.App.Env == "prod" {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
@@ -55,7 +67,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WebSocket
|
// WebSocket
|
||||||
r.GET("/ws", ws.ServeWS(sessionMgr))
|
r.GET("/ws", ws.ServeWS(sessionMgr, orch))
|
||||||
|
|
||||||
// HTTP Server
|
// HTTP Server
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/hhs/camtalk/internal/errors"
|
"github.com/hhs/camtalk/internal/errors"
|
||||||
"github.com/hhs/camtalk/internal/logger"
|
"github.com/hhs/camtalk/internal/logger"
|
||||||
"github.com/hhs/camtalk/internal/models"
|
"github.com/hhs/camtalk/internal/models"
|
||||||
|
"github.com/hhs/camtalk/internal/orchestrator"
|
||||||
"github.com/hhs/camtalk/internal/session"
|
"github.com/hhs/camtalk/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ var upgrader = websocket.Upgrader{
|
|||||||
type Client struct {
|
type Client struct {
|
||||||
conn *websocket.Conn
|
conn *websocket.Conn
|
||||||
sessionID string
|
sessionID string
|
||||||
|
sessionMgr session.Manager
|
||||||
|
orchestrator orchestrator.Orchestrator
|
||||||
|
cancelFuncs map[string]context.CancelFunc // requestID → cancel func
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,14 +38,50 @@ func (c *Client) SendJSON(v any) error {
|
|||||||
return c.conn.WriteJSON(v)
|
return c.conn.WriteJSON(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WSClient 实现 orchestrator.Sender 接口,将消息推送到 WebSocket 连接。
|
||||||
|
type WSClient struct {
|
||||||
|
client *Client
|
||||||
|
requestID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendSTTResult 发送语音识别结果。
|
||||||
|
func (w *WSClient) SendSTTResult(result models.WsSTTResult) error {
|
||||||
|
result.RequestID = w.requestID
|
||||||
|
return w.client.SendJSON(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendLLMChunk 发送 LLM 流式文本增量。
|
||||||
|
func (w *WSClient) SendLLMChunk(chunk models.WsLLMChunk) error {
|
||||||
|
chunk.RequestID = w.requestID
|
||||||
|
return w.client.SendJSON(chunk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendLLMDone 发送 LLM 流结束信号。
|
||||||
|
func (w *WSClient) SendLLMDone(done models.WsLLMDone) error {
|
||||||
|
done.RequestID = w.requestID
|
||||||
|
return w.client.SendJSON(done)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendTTSAudio 发送 TTS 音频数据。
|
||||||
|
func (w *WSClient) SendTTSAudio(audio models.WsTTSAudio) error {
|
||||||
|
audio.RequestID = w.requestID
|
||||||
|
return w.client.SendJSON(audio)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendError 发送错误消息。
|
||||||
|
func (w *WSClient) SendError(err models.WsError) error {
|
||||||
|
err.RequestID = w.requestID
|
||||||
|
return w.client.SendJSON(err)
|
||||||
|
}
|
||||||
|
|
||||||
// ServeWS 处理 WebSocket 升级请求。
|
// ServeWS 处理 WebSocket 升级请求。
|
||||||
func ServeWS(sessionMgr session.Manager) gin.HandlerFunc {
|
func ServeWS(sessionMgr session.Manager, orch orchestrator.Orchestrator) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
serveWS(c, sessionMgr)
|
serveWS(c, sessionMgr, orch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveWS(c *gin.Context, sessionMgr session.Manager) {
|
func serveWS(c *gin.Context, sessionMgr session.Manager, orch orchestrator.Orchestrator) {
|
||||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Errorw("websocket upgrade failed", "error", err)
|
logger.Log.Errorw("websocket upgrade failed", "error", err)
|
||||||
@@ -56,7 +96,13 @@ func serveWS(c *gin.Context, sessionMgr session.Manager) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &Client{conn: conn, sessionID: sessionID}
|
client := &Client{
|
||||||
|
conn: conn,
|
||||||
|
sessionID: sessionID,
|
||||||
|
sessionMgr: sessionMgr,
|
||||||
|
orchestrator: orch,
|
||||||
|
cancelFuncs: make(map[string]context.CancelFunc),
|
||||||
|
}
|
||||||
|
|
||||||
// 发送 connected 消息
|
// 发送 connected 消息
|
||||||
_ = client.SendJSON(models.WsConnected{
|
_ = client.SendJSON(models.WsConnected{
|
||||||
|
|||||||
Reference in New Issue
Block a user