llm,doc
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package api
|
||||
|
||||
type ApiGroup struct {
|
||||
LLMApi
|
||||
}
|
||||
|
||||
var ApiGroupApp = new(ApiGroup)
|
||||
@@ -0,0 +1,177 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/model/request"
|
||||
volcengineResponse "github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/model/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type LLMApi struct{}
|
||||
|
||||
// ChatCompletion
|
||||
// @Tags Volcengine
|
||||
// @Summary LLM聊天完成
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.ChatRequest true "聊天请求参数"
|
||||
// @Success 200 {object} response.Response{data=volcengineResponse.ChatResponse} "聊天响应"
|
||||
// @Router /volcengine/llm/chat [post]
|
||||
func (l *LLMApi) ChatCompletion(c *gin.Context) {
|
||||
var chatReq request.ChatRequest
|
||||
err := c.ShouldBindJSON(&chatReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成请求ID
|
||||
if chatReq.RequestID == "" {
|
||||
chatReq.RequestID = uuid.New().String()
|
||||
}
|
||||
|
||||
// 根据stream参数选择响应模式
|
||||
if chatReq.Stream {
|
||||
// 流式响应 (SSE)
|
||||
l.handleStreamResponse(c, chatReq)
|
||||
} else {
|
||||
// 普通JSON响应
|
||||
l.handleNormalResponse(c, chatReq)
|
||||
}
|
||||
}
|
||||
|
||||
// handleNormalResponse 处理普通JSON响应
|
||||
func (l *LLMApi) handleNormalResponse(c *gin.Context, chatReq request.ChatRequest) {
|
||||
resp, err := service.LLMServiceApp.ChatCompletion(chatReq)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("聊天完成失败!", zap.Error(err), zap.String("requestID", chatReq.RequestID))
|
||||
response.FailWithMessage("聊天完成失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
global.GVA_LOG.Info("聊天完成成功", zap.String("requestID", chatReq.RequestID))
|
||||
response.OkWithDetailed(resp, "聊天完成成功", c)
|
||||
}
|
||||
|
||||
// handleStreamResponse 处理流式响应 (SSE)
|
||||
func (l *LLMApi) handleStreamResponse(c *gin.Context, chatReq request.ChatRequest) {
|
||||
// 设置SSE响应头
|
||||
c.Header("Content-Type", "text/event-stream")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
c.Header("Connection", "keep-alive")
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Access-Control-Allow-Headers", "Cache-Control")
|
||||
|
||||
// 创建事件通道
|
||||
eventChan := make(chan volcengineResponse.StreamEvent, 100)
|
||||
defer close(eventChan)
|
||||
|
||||
// 启动流式处理
|
||||
go func() {
|
||||
err := service.LLMServiceApp.StreamChatCompletion(chatReq, eventChan)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("流式聊天失败!", zap.Error(err), zap.String("requestID", chatReq.RequestID))
|
||||
eventChan <- volcengineResponse.StreamEvent{
|
||||
Event: "error",
|
||||
Data: volcengineResponse.ChatResponse{
|
||||
ID: chatReq.RequestID,
|
||||
Error: &volcengineResponse.APIError{
|
||||
Code: "stream_error",
|
||||
Message: err.Error(),
|
||||
Type: "internal_error",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 发送流式数据
|
||||
c.Stream(func(w io.Writer) bool {
|
||||
select {
|
||||
case event, ok := <-eventChan:
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch event.Event {
|
||||
case "message":
|
||||
// 发送消息事件
|
||||
c.SSEvent("message", event.Data)
|
||||
case "error":
|
||||
// 发送错误事件
|
||||
c.SSEvent("error", event.Data)
|
||||
return false
|
||||
case "done":
|
||||
// 发送完成事件
|
||||
c.SSEvent("done", event.Data)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
case <-time.After(30 * time.Second):
|
||||
// 超时处理
|
||||
c.SSEvent("error", volcengineResponse.ChatResponse{
|
||||
ID: chatReq.RequestID,
|
||||
Error: &volcengineResponse.APIError{
|
||||
Code: "timeout",
|
||||
Message: "Stream timeout",
|
||||
Type: "timeout_error",
|
||||
},
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// StopGeneration
|
||||
// @Tags Volcengine
|
||||
// @Summary 停止LLM生成
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.StopRequest true "停止请求参数"
|
||||
// @Success 200 {object} response.Response{data=volcengineResponse.StopResponse} "停止响应"
|
||||
// @Router /volcengine/llm/stop [post]
|
||||
func (l *LLMApi) StopGeneration(c *gin.Context) {
|
||||
var stopReq request.StopRequest
|
||||
err := c.ShouldBindJSON(&stopReq)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := service.LLMServiceApp.StopGeneration(stopReq)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("停止生成失败!", zap.Error(err), zap.String("requestID", stopReq.RequestID))
|
||||
response.FailWithMessage("停止生成失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.Success {
|
||||
global.GVA_LOG.Info("停止生成成功", zap.String("requestID", stopReq.RequestID))
|
||||
response.OkWithDetailed(resp, "停止生成成功", c)
|
||||
} else {
|
||||
global.GVA_LOG.Warn("停止生成失败", zap.String("requestID", stopReq.RequestID), zap.String("reason", resp.Message))
|
||||
response.FailWithDetailed(resp, resp.Message, c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetActiveSessionsCount
|
||||
// @Tags Volcengine
|
||||
// @Summary 获取活跃会话数量
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=int} "活跃会话数量"
|
||||
// @Router /volcengine/llm/sessions [get]
|
||||
func (l *LLMApi) GetActiveSessionsCount(c *gin.Context) {
|
||||
count := service.LLMServiceApp.GetActiveSessionsCount()
|
||||
response.OkWithDetailed(gin.H{"count": count}, fmt.Sprintf("当前活跃会话数量: %d", count), c)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package volcengine
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/router"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type volcenginePlugin struct{}
|
||||
|
||||
// CreateVolcenginePlug 创建volcengine插件实例
|
||||
func CreateVolcenginePlug() *volcenginePlugin {
|
||||
return &volcenginePlugin{}
|
||||
}
|
||||
|
||||
// Register 注册路由
|
||||
func (*volcenginePlugin) Register(group *gin.RouterGroup) {
|
||||
router.RouterGroupApp.InitLLMRouter(group)
|
||||
}
|
||||
|
||||
// RouterPath 返回注册路由路径
|
||||
func (*volcenginePlugin) RouterPath() string {
|
||||
return "volcengine"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package request
|
||||
|
||||
// Message 聊天消息结构体
|
||||
type Message struct {
|
||||
Role string `json:"role" form:"role" binding:"required"` // 角色: system, user, assistant
|
||||
Content string `json:"content" form:"content" binding:"required"` // 消息内容
|
||||
}
|
||||
|
||||
// ChatRequest 聊天请求结构体
|
||||
type ChatRequest struct {
|
||||
Messages []Message `json:"messages" form:"messages" binding:"required"` // 对话消息列表
|
||||
Model string `json:"model" form:"model"` // 模型名称,如果为空则使用默认模型
|
||||
Stream bool `json:"stream" form:"stream"` // 是否流式响应,默认false
|
||||
Temperature float64 `json:"temperature" form:"temperature"` // 温度参数,控制随机性,范围0-1
|
||||
MaxTokens int `json:"max_tokens" form:"max_tokens"` // 最大生成token数
|
||||
TopP float64 `json:"top_p" form:"top_p"` // 核采样参数
|
||||
RequestID string `json:"request_id,omitempty" form:"request_id,omitempty"` // 请求ID,用于流式响应管理
|
||||
}
|
||||
|
||||
// StopRequest 停止生成请求结构体
|
||||
type StopRequest struct {
|
||||
RequestID string `json:"request_id" form:"request_id" binding:"required"` // 要停止的请求ID
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package response
|
||||
|
||||
import "time"
|
||||
|
||||
// Message 聊天消息结构体
|
||||
type Message struct {
|
||||
Role string `json:"role"` // 角色: system, user, assistant
|
||||
Content string `json:"content"` // 消息内容
|
||||
}
|
||||
|
||||
// Choice 响应选择结构体
|
||||
type Choice struct {
|
||||
Index int `json:"index"` // 选择索引
|
||||
Message Message `json:"message,omitempty"` // 完整响应消息(非流式)
|
||||
Delta Message `json:"delta,omitempty"` // 增量消息(流式)
|
||||
FinishReason string `json:"finish_reason,omitempty"` // 结束原因: stop, length, content_filter
|
||||
}
|
||||
|
||||
// Usage 使用量统计结构体
|
||||
type Usage struct {
|
||||
PromptTokens int `json:"prompt_tokens"` // 输入token数
|
||||
CompletionTokens int `json:"completion_tokens"` // 输出token数
|
||||
TotalTokens int `json:"total_tokens"` // 总token数
|
||||
}
|
||||
|
||||
// APIError API错误结构体
|
||||
type APIError struct {
|
||||
Code string `json:"code"` // 错误代码
|
||||
Message string `json:"message"` // 错误消息
|
||||
Type string `json:"type"` // 错误类型
|
||||
}
|
||||
|
||||
// ChatResponse 聊天响应结构体
|
||||
type ChatResponse struct {
|
||||
ID string `json:"id"` // 响应ID
|
||||
Object string `json:"object"` // 对象类型: chat.completion 或 chat.completion.chunk
|
||||
Created int64 `json:"created"` // 创建时间戳
|
||||
Model string `json:"model"` // 使用的模型
|
||||
Choices []Choice `json:"choices"` // 响应选择列表
|
||||
Usage *Usage `json:"usage,omitempty"` // 使用量统计(非流式响应)
|
||||
Error *APIError `json:"error,omitempty"` // 错误信息
|
||||
}
|
||||
|
||||
// StopResponse 停止生成响应结构体
|
||||
type StopResponse struct {
|
||||
Success bool `json:"success"` // 是否成功停止
|
||||
Message string `json:"message"` // 响应消息
|
||||
RequestID string `json:"request_id"` // 请求ID
|
||||
StoppedAt int64 `json:"stopped_at"` // 停止时间戳
|
||||
}
|
||||
|
||||
// StreamEvent 流式事件结构体
|
||||
type StreamEvent struct {
|
||||
Event string `json:"event"` // 事件类型: message, error, done
|
||||
Data ChatResponse `json:"data"` // 事件数据
|
||||
}
|
||||
|
||||
// ChatSession 聊天会话管理结构体(用于内部管理)
|
||||
type ChatSession struct {
|
||||
RequestID string `json:"request_id"` // 请求ID
|
||||
UserID uint `json:"user_id"` // 用户ID
|
||||
Model string `json:"model"` // 使用的模型
|
||||
StartTime time.Time `json:"start_time"` // 开始时间
|
||||
IsStreaming bool `json:"is_streaming"` // 是否流式响应
|
||||
Status string `json:"status"` // 状态: running, completed, stopped, error
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package router
|
||||
|
||||
type RouterGroup struct {
|
||||
LLMRouter
|
||||
}
|
||||
|
||||
var RouterGroupApp = new(RouterGroup)
|
||||
@@ -0,0 +1,30 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/middleware"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type LLMRouter struct{}
|
||||
|
||||
// InitLLMRouter 初始化LLM路由
|
||||
func (l *LLMRouter) InitLLMRouter(Router *gin.RouterGroup) {
|
||||
// LLM相关路由组,使用操作记录中间件
|
||||
llmRouter := Router.Group("llm").Use(middleware.OperationRecord())
|
||||
// LLM查询路由组,不使用操作记录中间件(用于GET请求)
|
||||
llmRouterWithoutRecord := Router.Group("llm")
|
||||
|
||||
// 获取API实例
|
||||
llmApi := api.ApiGroupApp.LLMApi
|
||||
|
||||
{
|
||||
// 需要记录操作的路由(POST请求)
|
||||
llmRouter.POST("chat", llmApi.ChatCompletion) // LLM聊天完成
|
||||
llmRouter.POST("stop", llmApi.StopGeneration) // 停止LLM生成
|
||||
}
|
||||
{
|
||||
// 不需要记录操作的路由(GET请求)
|
||||
llmRouterWithoutRecord.GET("sessions", llmApi.GetActiveSessionsCount) // 获取活跃会话数量
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/model/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine/model/response"
|
||||
"github.com/google/uuid"
|
||||
"github.com/volcengine/volcengine-go-sdk/service/arkruntime"
|
||||
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type LLMService struct {
|
||||
client *arkruntime.Client
|
||||
activeSessions sync.Map // requestID -> context.CancelFunc
|
||||
}
|
||||
|
||||
var LLMServiceApp = new(LLMService)
|
||||
|
||||
// InitVolcengineClient 初始化火山引擎客户端
|
||||
func (l *LLMService) InitVolcengineClient() error {
|
||||
config := global.GVA_CONFIG.Volcengine
|
||||
|
||||
// 验证配置
|
||||
if config.AccessKey == "" || config.SecretKey == "" {
|
||||
return fmt.Errorf("volcengine access key or secret key is empty")
|
||||
}
|
||||
|
||||
// 创建ARK Runtime客户端
|
||||
l.client = arkruntime.NewClientWithAkSk(config.AccessKey, config.SecretKey)
|
||||
|
||||
global.GVA_LOG.Info("Volcengine client initialized successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChatCompletion 非流式聊天完成
|
||||
func (l *LLMService) ChatCompletion(req request.ChatRequest) (*response.ChatResponse, error) {
|
||||
if l.client == nil {
|
||||
if err := l.InitVolcengineClient(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 生成请求ID
|
||||
if req.RequestID == "" {
|
||||
req.RequestID = uuid.New().String()
|
||||
}
|
||||
|
||||
// 转换消息格式
|
||||
messages := make([]*model.ChatCompletionMessage, len(req.Messages))
|
||||
for i, msg := range req.Messages {
|
||||
messages[i] = &model.ChatCompletionMessage{
|
||||
Role: msg.Role,
|
||||
Content: &model.ChatCompletionMessageContent{
|
||||
StringValue: &msg.Content,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 设置模型
|
||||
modelName := req.Model
|
||||
if modelName == "" {
|
||||
modelName = global.GVA_CONFIG.Volcengine.DefaultModel
|
||||
}
|
||||
|
||||
// 创建请求
|
||||
chatReq := &model.ChatCompletionRequest{
|
||||
Model: modelName,
|
||||
Messages: messages,
|
||||
}
|
||||
|
||||
// 设置可选参数
|
||||
if req.Temperature > 0 {
|
||||
chatReq.Temperature = float32(req.Temperature)
|
||||
}
|
||||
if req.MaxTokens > 0 {
|
||||
chatReq.MaxTokens = req.MaxTokens
|
||||
}
|
||||
if req.TopP > 0 {
|
||||
chatReq.TopP = float32(req.TopP)
|
||||
}
|
||||
|
||||
// 创建上下文
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// 存储取消函数
|
||||
l.activeSessions.Store(req.RequestID, cancel)
|
||||
defer l.activeSessions.Delete(req.RequestID)
|
||||
|
||||
// 调用API
|
||||
resp, err := l.client.CreateChatCompletion(ctx, chatReq)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("Chat completion failed", zap.Error(err), zap.String("requestID", req.RequestID))
|
||||
return nil, fmt.Errorf("chat completion failed: %w", err)
|
||||
}
|
||||
|
||||
// 转换响应格式
|
||||
chatResp := &response.ChatResponse{
|
||||
ID: req.RequestID,
|
||||
Object: "chat.completion",
|
||||
Created: time.Now().Unix(),
|
||||
Model: modelName,
|
||||
Choices: make([]response.Choice, len(resp.Choices)),
|
||||
}
|
||||
|
||||
for i, choice := range resp.Choices {
|
||||
messageContent := ""
|
||||
if choice.Message.Content != nil && choice.Message.Content.StringValue != nil {
|
||||
messageContent = *choice.Message.Content.StringValue
|
||||
}
|
||||
|
||||
chatResp.Choices[i] = response.Choice{
|
||||
Index: i,
|
||||
Message: response.Message{
|
||||
Role: choice.Message.Role,
|
||||
Content: messageContent,
|
||||
},
|
||||
FinishReason: string(choice.FinishReason),
|
||||
}
|
||||
}
|
||||
|
||||
// 设置使用量统计
|
||||
chatResp.Usage = &response.Usage{
|
||||
PromptTokens: resp.Usage.PromptTokens,
|
||||
CompletionTokens: resp.Usage.CompletionTokens,
|
||||
TotalTokens: resp.Usage.TotalTokens,
|
||||
}
|
||||
|
||||
global.GVA_LOG.Info("Chat completion successful", zap.String("requestID", req.RequestID))
|
||||
return chatResp, nil
|
||||
}
|
||||
|
||||
// StreamChatCompletion 流式聊天完成
|
||||
func (l *LLMService) StreamChatCompletion(req request.ChatRequest, eventChan chan<- response.StreamEvent) error {
|
||||
if l.client == nil {
|
||||
if err := l.InitVolcengineClient(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 生成请求ID
|
||||
if req.RequestID == "" {
|
||||
req.RequestID = uuid.New().String()
|
||||
}
|
||||
|
||||
// 转换消息格式
|
||||
messages := make([]*model.ChatCompletionMessage, len(req.Messages))
|
||||
for i, msg := range req.Messages {
|
||||
messages[i] = &model.ChatCompletionMessage{
|
||||
Role: msg.Role,
|
||||
Content: &model.ChatCompletionMessageContent{
|
||||
StringValue: &msg.Content,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 设置模型
|
||||
modelName := req.Model
|
||||
if modelName == "" {
|
||||
modelName = global.GVA_CONFIG.Volcengine.DefaultModel
|
||||
}
|
||||
|
||||
// 创建流式请求
|
||||
chatReq := &model.ChatCompletionRequest{
|
||||
Model: modelName,
|
||||
Messages: messages,
|
||||
Stream: true,
|
||||
}
|
||||
|
||||
// 设置可选参数
|
||||
if req.Temperature > 0 {
|
||||
chatReq.Temperature = float32(req.Temperature)
|
||||
}
|
||||
if req.MaxTokens > 0 {
|
||||
chatReq.MaxTokens = req.MaxTokens
|
||||
}
|
||||
if req.TopP > 0 {
|
||||
chatReq.TopP = float32(req.TopP)
|
||||
}
|
||||
|
||||
// 创建上下文
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) // 流式响应需要更长时间
|
||||
defer cancel()
|
||||
|
||||
// 存储取消函数
|
||||
l.activeSessions.Store(req.RequestID, cancel)
|
||||
defer l.activeSessions.Delete(req.RequestID)
|
||||
|
||||
// 调用流式API
|
||||
stream_resp, err := l.client.CreateChatCompletionStream(ctx, chatReq)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("Stream chat completion failed", zap.Error(err), zap.String("requestID", req.RequestID))
|
||||
return fmt.Errorf("stream chat completion failed: %w", err)
|
||||
}
|
||||
defer stream_resp.Close()
|
||||
|
||||
// 处理流式响应
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// 上下文取消
|
||||
eventChan <- response.StreamEvent{
|
||||
Event: "error",
|
||||
Data: response.ChatResponse{
|
||||
ID: req.RequestID,
|
||||
Error: &response.APIError{
|
||||
Code: "context_cancelled",
|
||||
Message: "Request was cancelled",
|
||||
Type: "request_cancelled",
|
||||
},
|
||||
},
|
||||
}
|
||||
return ctx.Err()
|
||||
default:
|
||||
// 接收流式数据
|
||||
recv, err := stream_resp.Recv()
|
||||
if err != nil {
|
||||
if err.Error() == "EOF" {
|
||||
// 流结束
|
||||
eventChan <- response.StreamEvent{
|
||||
Event: "done",
|
||||
Data: response.ChatResponse{
|
||||
ID: req.RequestID,
|
||||
Object: "chat.completion.chunk",
|
||||
},
|
||||
}
|
||||
global.GVA_LOG.Info("Stream chat completion finished", zap.String("requestID", req.RequestID))
|
||||
return nil
|
||||
}
|
||||
global.GVA_LOG.Error("Stream receive error", zap.Error(err), zap.String("requestID", req.RequestID))
|
||||
eventChan <- response.StreamEvent{
|
||||
Event: "error",
|
||||
Data: response.ChatResponse{
|
||||
ID: req.RequestID,
|
||||
Error: &response.APIError{
|
||||
Code: "stream_error",
|
||||
Message: err.Error(),
|
||||
Type: "stream_error",
|
||||
},
|
||||
},
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 转换并发送响应
|
||||
chatResp := response.ChatResponse{
|
||||
ID: req.RequestID,
|
||||
Object: "chat.completion.chunk",
|
||||
Created: time.Now().Unix(),
|
||||
Model: modelName,
|
||||
Choices: make([]response.Choice, len(recv.Choices)),
|
||||
}
|
||||
|
||||
for i, choice := range recv.Choices {
|
||||
chatResp.Choices[i] = response.Choice{
|
||||
Index: i,
|
||||
Delta: response.Message{
|
||||
Role: choice.Delta.Role,
|
||||
Content: choice.Delta.Content,
|
||||
},
|
||||
}
|
||||
if choice.FinishReason != "" {
|
||||
chatResp.Choices[i].FinishReason = string(choice.FinishReason)
|
||||
}
|
||||
}
|
||||
|
||||
eventChan <- response.StreamEvent{
|
||||
Event: "message",
|
||||
Data: chatResp,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StopGeneration 停止生成
|
||||
func (l *LLMService) StopGeneration(req request.StopRequest) (*response.StopResponse, error) {
|
||||
// 查找并取消对应的请求
|
||||
if cancelFunc, ok := l.activeSessions.Load(req.RequestID); ok {
|
||||
if cancel, ok := cancelFunc.(context.CancelFunc); ok {
|
||||
cancel()
|
||||
l.activeSessions.Delete(req.RequestID)
|
||||
|
||||
global.GVA_LOG.Info("Request stopped successfully", zap.String("requestID", req.RequestID))
|
||||
return &response.StopResponse{
|
||||
Success: true,
|
||||
Message: "Request stopped successfully",
|
||||
RequestID: req.RequestID,
|
||||
StoppedAt: time.Now().Unix(),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
global.GVA_LOG.Warn("Request not found or already completed", zap.String("requestID", req.RequestID))
|
||||
return &response.StopResponse{
|
||||
Success: false,
|
||||
Message: "Request not found or already completed",
|
||||
RequestID: req.RequestID,
|
||||
StoppedAt: time.Now().Unix(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetActiveSessionsCount 获取活跃会话数量
|
||||
func (l *LLMService) GetActiveSessionsCount() int {
|
||||
count := 0
|
||||
l.activeSessions.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
return count
|
||||
}
|
||||
Reference in New Issue
Block a user