This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
petRequest "github.com/flipped-aurora/gin-vue-admin/server/model/pet/request"
|
||||
petResponse "github.com/flipped-aurora/gin-vue-admin/server/model/pet/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -19,162 +15,6 @@ type PetAssistantApi struct{}
|
||||
|
||||
var petChatService = service.ServiceGroupApp.PetServiceGroup.PetChatService
|
||||
|
||||
// AskPetAssistant 向宠物助手提问(非流式)
|
||||
// @Tags PetAssistant
|
||||
// @Summary 向宠物助手提问
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body petRequest.ChatRequest true "宠物助手提问请求"
|
||||
// @Success 200 {object} response.Response{data=petResponse.ChatResponse,msg=string} "提问成功"
|
||||
// @Router /api/v1/pet/user/assistant/ask [post]
|
||||
func (p *PetAssistantApi) AskPetAssistant(ctx *gin.Context) {
|
||||
// 创建业务用Context
|
||||
businessCtx := ctx.Request.Context()
|
||||
|
||||
// 获取用户ID
|
||||
userId := utils.GetAppUserID(ctx)
|
||||
if userId == 0 {
|
||||
global.GVA_LOG.Error("获取用户ID失败")
|
||||
response.FailWithMessage("用户认证失败", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 绑定请求参数
|
||||
var req petRequest.ChatRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
global.GVA_LOG.Error("参数绑定失败", zap.Error(err))
|
||||
response.FailWithMessage("参数错误: "+err.Error(), ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 参数验证
|
||||
if req.Message == "" {
|
||||
response.FailWithMessage("消息内容不能为空", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 设置默认参数
|
||||
if req.Temperature <= 0 {
|
||||
req.Temperature = 0.7
|
||||
}
|
||||
if req.MaxTokens <= 0 {
|
||||
req.MaxTokens = 1000
|
||||
}
|
||||
|
||||
// 调用服务层
|
||||
resp, err := petChatService.SendMessage(businessCtx, userId, req)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("发送消息失败", zap.Error(err), zap.Uint("userId", userId))
|
||||
response.FailWithMessage("发送消息失败: "+err.Error(), ctx)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithDetailed(resp, "发送成功", ctx)
|
||||
}
|
||||
|
||||
// StreamAskPetAssistant 向宠物助手流式提问
|
||||
// @Tags PetAssistant
|
||||
// @Summary 向宠物助手流式提问接口
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce text/event-stream
|
||||
// @Param data body petRequest.ChatRequest true "宠物助手流式提问请求"
|
||||
// @Success 200 {string} string "流式响应"
|
||||
// @Router /api/v1/pet/user/assistant/stream-ask [post]
|
||||
func (p *PetAssistantApi) StreamAskPetAssistant(ctx *gin.Context) {
|
||||
// 创建业务用Context
|
||||
businessCtx := ctx.Request.Context()
|
||||
|
||||
// 获取用户ID
|
||||
userId := utils.GetAppUserID(ctx)
|
||||
if userId == 0 {
|
||||
global.GVA_LOG.Error("获取用户ID失败")
|
||||
response.FailWithMessage("用户认证失败", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 绑定请求参数
|
||||
var req petRequest.ChatRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
global.GVA_LOG.Error("参数绑定失败", zap.Error(err))
|
||||
response.FailWithMessage("参数错误: "+err.Error(), ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 参数验证
|
||||
if req.Message == "" {
|
||||
response.FailWithMessage("消息内容不能为空", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 强制设置为流式响应
|
||||
req.Stream = true
|
||||
|
||||
// 设置默认参数
|
||||
if req.Temperature <= 0 {
|
||||
req.Temperature = 0.7
|
||||
}
|
||||
if req.MaxTokens <= 0 {
|
||||
req.MaxTokens = 1000
|
||||
}
|
||||
|
||||
// 设置SSE响应头
|
||||
ctx.Header("Content-Type", "text/event-stream")
|
||||
ctx.Header("Cache-Control", "no-cache")
|
||||
ctx.Header("Connection", "keep-alive")
|
||||
ctx.Header("Access-Control-Allow-Origin", "*")
|
||||
ctx.Header("Access-Control-Allow-Headers", "Cache-Control")
|
||||
|
||||
// 创建事件通道
|
||||
eventChan := make(chan petResponse.StreamEvent, 100)
|
||||
defer close(eventChan)
|
||||
|
||||
// 启动流式聊天
|
||||
go func() {
|
||||
if err := petChatService.StreamChat(businessCtx, userId, req, eventChan); err != nil {
|
||||
global.GVA_LOG.Error("流式聊天失败", zap.Error(err), zap.Uint("userId", userId))
|
||||
eventChan <- petResponse.StreamEvent{
|
||||
Event: "error",
|
||||
Data: map[string]interface{}{
|
||||
"error": "流式聊天失败: " + err.Error(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 发送流式数据
|
||||
ctx.Stream(func(w io.Writer) bool {
|
||||
select {
|
||||
case event, ok := <-eventChan:
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch event.Event {
|
||||
case "message":
|
||||
// 发送消息事件
|
||||
ctx.SSEvent("message", event.Data)
|
||||
case "error":
|
||||
// 发送错误事件
|
||||
ctx.SSEvent("error", event.Data)
|
||||
return false
|
||||
case "done":
|
||||
// 发送完成事件
|
||||
ctx.SSEvent("done", event.Data)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
case <-time.After(30 * time.Second):
|
||||
// 超时处理
|
||||
ctx.SSEvent("error", map[string]interface{}{
|
||||
"error": "流式响应超时",
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// GetAssistantHistory 获取宠物助手对话历史
|
||||
// @Tags PetAssistant
|
||||
// @Summary 获取宠物助手对话历史记录(简化版本,只返回必要字段)
|
||||
|
||||
Reference in New Issue
Block a user