From e03259608e389efd18668785cd1ab57256a5ce79 Mon Sep 17 00:00:00 2001 From: yvan <8574526@qq.com> Date: Sat, 2 Aug 2025 23:54:03 +0800 Subject: [PATCH] =?UTF-8?q?llm=EF=BC=8Cdoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/config.yaml | 8 +- server/config/config.go | 3 + server/config/volcengine.go | 9 + server/docs/docs.go | 1273 ++++++++++++++++- server/docs/swagger.json | 1270 +++++++++++++++- server/docs/swagger.yaml | 783 +++++++++- server/go.mod | 3 + server/go.sum | 26 + server/initialize/plugin_biz_v1.go | 24 +- server/plugin/volcengine/api/enter.go | 7 + server/plugin/volcengine/api/llm_api.go | 177 +++ server/plugin/volcengine/main.go | 23 + server/plugin/volcengine/model/request/llm.go | 23 + .../plugin/volcengine/model/response/llm.go | 66 + server/plugin/volcengine/router/enter.go | 7 + server/plugin/volcengine/router/llm_router.go | 30 + .../plugin/volcengine/service/llm_service.go | 316 ++++ 17 files changed, 3836 insertions(+), 212 deletions(-) create mode 100644 server/config/volcengine.go create mode 100644 server/plugin/volcengine/api/enter.go create mode 100644 server/plugin/volcengine/api/llm_api.go create mode 100644 server/plugin/volcengine/main.go create mode 100644 server/plugin/volcengine/model/request/llm.go create mode 100644 server/plugin/volcengine/model/response/llm.go create mode 100644 server/plugin/volcengine/router/enter.go create mode 100644 server/plugin/volcengine/router/llm_router.go create mode 100644 server/plugin/volcengine/service/llm_service.go diff --git a/server/config.yaml b/server/config.yaml index 73f40b56..e9b32462 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -10,7 +10,7 @@ autocode: root: /Users/yvan/GolandProjects/yvan/pet-ai server: server module: github.com/flipped-aurora/gin-vue-admin/server - ai-path: "" + ai-path: "https://ai.gin-vue-admin.com/{FUNC}/xyvan329/fb12d6eb-4e21-4ed3-8fb3-9013d57ccf44" aws-s3: bucket: xxxxx-10005608 region: ap-shanghai @@ -236,6 +236,12 @@ tencent-cos: secret-key: your-secret-key base-url: https://gin.vue.admin path-prefix: github.com/flipped-aurora/gin-vue-admin/server +volcengine: + access-key: "your-access-key" + secret-key: "your-secret-key" + region: "cn-beijing" + endpoint: "https://ark.cn-beijing.volces.com" + default-model: "ep-xxx" zap: level: info prefix: '[github.com/flipped-aurora/gin-vue-admin/server]' diff --git a/server/config/config.go b/server/config/config.go index 3abac5ac..495a63fa 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -37,4 +37,7 @@ type Server struct { // MCP配置 MCP MCP `mapstructure:"mcp" json:"mcp" yaml:"mcp"` + + // Volcengine配置 + Volcengine Volcengine `mapstructure:"volcengine" json:"volcengine" yaml:"volcengine"` } diff --git a/server/config/volcengine.go b/server/config/volcengine.go new file mode 100644 index 00000000..fd45b9e4 --- /dev/null +++ b/server/config/volcengine.go @@ -0,0 +1,9 @@ +package config + +type Volcengine struct { + AccessKey string `mapstructure:"access-key" json:"access-key" yaml:"access-key"` // 火山引擎访问密钥ID + SecretKey string `mapstructure:"secret-key" json:"secret-key" yaml:"secret-key"` // 火山引擎访问密钥Secret + Region string `mapstructure:"region" json:"region" yaml:"region"` // 区域,如:cn-beijing + Endpoint string `mapstructure:"endpoint" json:"endpoint" yaml:"endpoint"` // 服务端点,如:https://ark.cn-beijing.volces.com + DefaultModel string `mapstructure:"default-model" json:"default-model" yaml:"default-model"` // 默认模型ID,如:ep-xxx +} diff --git a/server/docs/docs.go b/server/docs/docs.go index 669b94b6..81813578 100644 --- a/server/docs/docs.go +++ b/server/docs/docs.go @@ -1,5 +1,4 @@ -// Code generated by swaggo/swag. DO NOT EDIT. - +// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -1806,9 +1805,7 @@ const docTemplate = `{ "properties": { "data": { "type": "array", - "items": { - "type": "object" - } + "items": {} }, "msg": { "type": "string" @@ -1821,6 +1818,120 @@ const docTemplate = `{ } } }, + "/autoCode/mcp": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "自动McpTool", + "parameters": [ + { + "description": "创建自动代码", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AutoMcpTool" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"创建成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/autoCode/mcpList": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "自动McpTool", + "parameters": [ + { + "description": "创建自动代码", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AutoMcpTool" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"创建成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/autoCode/mcpTest": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "测试McpTool", + "parameters": [ + { + "description": "调用MCP Tool的参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "type": "object" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"测试成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/autoCode/preview": { "post": { "security": [ @@ -4577,26 +4688,6 @@ const docTemplate = `{ } } }, - "/sysExportTemplate/ExportTemplate": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SysExportTemplate" - ], - "summary": "导出表格模板", - "responses": {} - } - }, "/sysExportTemplate/createSysExportTemplate": { "post": { "security": [ @@ -4731,6 +4822,66 @@ const docTemplate = `{ "responses": {} } }, + "/sysExportTemplate/exportExcelByToken": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExportExcelByToken" + ], + "summary": "导出表格", + "responses": {} + } + }, + "/sysExportTemplate/exportTemplate": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysExportTemplate" + ], + "summary": "导出表格模板", + "responses": {} + } + }, + "/sysExportTemplate/exportTemplateByToken": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExportTemplateByToken" + ], + "summary": "通过token导出表格模板", + "responses": {} + } + }, "/sysExportTemplate/findSysExportTemplate": { "get": { "security": [ @@ -4991,56 +5142,6 @@ const docTemplate = `{ } } }, - "/sysOperationRecord/createSysOperationRecord": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SysOperationRecord" - ], - "summary": "创建SysOperationRecord", - "parameters": [ - { - "description": "创建SysOperationRecord", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/system.SysOperationRecord" - } - } - ], - "responses": { - "200": { - "description": "创建SysOperationRecord", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.Response" - }, - { - "type": "object", - "properties": { - "msg": { - "type": "string" - } - } - } - ] - } - } - } - } - }, "/sysOperationRecord/deleteSysOperationRecord": { "delete": { "security": [ @@ -5815,6 +5916,415 @@ const docTemplate = `{ } } }, + "/sysVersion/deleteSysVersion": { + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "删除版本管理", + "parameters": [ + { + "description": "删除版本管理", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysVersion" + } + } + ], + "responses": { + "200": { + "description": "删除成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/deleteSysVersionByIds": { + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "批量删除版本管理", + "responses": { + "200": { + "description": "批量删除成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/downloadVersionJson": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "下载版本JSON数据", + "parameters": [ + { + "type": "string", + "description": "版本ID", + "name": "ID", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "下载成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/exportVersion": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "创建发版数据", + "parameters": [ + { + "description": "创建发版数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ExportVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "创建成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/findSysVersion": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "用id查询版本管理", + "parameters": [ + { + "type": "integer", + "description": "用id查询版本管理", + "name": "ID", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "查询成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysVersion" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/getSysVersionList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "分页获取版本管理列表", + "parameters": [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "name": "createdAtRange", + "in": "query" + }, + { + "type": "string", + "description": "关键字", + "name": "keyword", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "name": "versionCode", + "in": "query" + }, + { + "type": "string", + "name": "versionName", + "in": "query" + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.PageResult" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/getSysVersionPublic": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "不需要鉴权的版本管理接口", + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/importVersion": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "导入版本数据", + "parameters": [ + { + "description": "版本JSON数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ImportVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "导入成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/system/getServerInfo": { "post": { "security": [ @@ -5907,10 +6417,10 @@ const docTemplate = `{ "tags": [ "System" ], - "summary": "重启系统", + "summary": "重载系统", "responses": { "200": { - "description": "重启系统", + "description": "重载系统", "schema": { "allOf": [ { @@ -6524,6 +7034,142 @@ const docTemplate = `{ } } } + }, + "/volcengine/llm/chat": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "LLM聊天完成", + "parameters": [ + { + "description": "聊天请求参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ChatRequest" + } + } + ], + "responses": { + "200": { + "description": "聊天响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.ChatResponse" + } + } + } + ] + } + } + } + } + }, + "/volcengine/llm/sessions": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "获取活跃会话数量", + "responses": { + "200": { + "description": "活跃会话数量", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "integer" + } + } + } + ] + } + } + } + } + }, + "/volcengine/llm/stop": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "停止LLM生成", + "parameters": [ + { + "description": "停止请求参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.StopRequest" + } + } + ], + "responses": { + "200": { + "description": "停止响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.StopResponse" + } + } + } + ] + } + } + } + } } }, "definitions": { @@ -6656,7 +7302,7 @@ const docTemplate = `{ "type": "integer" }, "open-captcha": { - "description": "防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码此数,如3代表错误三次后出现验证码", + "description": "防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码次数,如3代表错误三次后出现验证码", "type": "integer" }, "open-captcha-timeout": { @@ -6758,6 +7404,31 @@ const docTemplate = `{ } } }, + "config.MCP": { + "type": "object", + "properties": { + "message_path": { + "description": "消息路径", + "type": "string" + }, + "name": { + "description": "MCP名称", + "type": "string" + }, + "sse_path": { + "description": "SSE路径", + "type": "string" + }, + "url_prefix": { + "description": "URL前缀", + "type": "string" + }, + "version": { + "description": "MCP版本", + "type": "string" + } + } + }, "config.Minio": { "type": "object", "properties": { @@ -7213,6 +7884,14 @@ const docTemplate = `{ } ] }, + "mcp": { + "description": "MCP配置", + "allOf": [ + { + "$ref": "#/definitions/config.MCP" + } + ] + }, "minio": { "$ref": "#/definitions/config.Minio" }, @@ -7257,6 +7936,14 @@ const docTemplate = `{ "tencent-cos": { "$ref": "#/definitions/config.TencentCOS" }, + "volcengine": { + "description": "Volcengine配置", + "allOf": [ + { + "$ref": "#/definitions/config.Volcengine" + } + ] + }, "zap": { "$ref": "#/definitions/config.Zap" } @@ -7452,6 +8139,31 @@ const docTemplate = `{ } } }, + "config.Volcengine": { + "type": "object", + "properties": { + "access-key": { + "description": "火山引擎访问密钥ID", + "type": "string" + }, + "default-model": { + "description": "默认模型ID,如:ep-xxx", + "type": "string" + }, + "endpoint": { + "description": "服务端点,如:https://ark.cn-beijing.volces.com", + "type": "string" + }, + "region": { + "description": "区域,如:cn-beijing", + "type": "string" + }, + "secret-key": { + "description": "火山引擎访问密钥Secret", + "type": "string" + } + } + }, "config.Zap": { "type": "object", "properties": { @@ -7675,6 +8387,10 @@ const docTemplate = `{ "description": "服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议", "type": "string" }, + "is-loginauth": { + "description": "是否LoginAuth 是否使用LoginAuth认证方式(适用于IBM、微软邮箱服务器等)", + "type": "boolean" + }, "is-ssl": { "description": "是否SSL 是否开启SSL", "type": "boolean" @@ -7961,6 +8677,65 @@ const docTemplate = `{ } } }, + "request.AutoMcpTool": { + "type": "object", + "required": [ + "description", + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "array", + "items": { + "type": "object", + "required": [ + "description", + "name", + "type" + ], + "properties": { + "default": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "type": { + "description": "string, number, boolean, object, array", + "type": "string" + } + } + } + }, + "response": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "text, image", + "type": "string" + } + } + } + } + } + }, "request.CasbinInReceive": { "type": "object", "properties": { @@ -8002,6 +8777,45 @@ const docTemplate = `{ } } }, + "request.ChatRequest": { + "type": "object", + "required": [ + "messages" + ], + "properties": { + "max_tokens": { + "description": "最大生成token数", + "type": "integer" + }, + "messages": { + "description": "对话消息列表", + "type": "array", + "items": { + "$ref": "#/definitions/request.Message" + } + }, + "model": { + "description": "模型名称,如果为空则使用默认模型", + "type": "string" + }, + "request_id": { + "description": "请求ID,用于流式响应管理", + "type": "string" + }, + "stream": { + "description": "是否流式响应,默认false", + "type": "boolean" + }, + "temperature": { + "description": "温度参数,控制随机性,范围0-1", + "type": "number" + }, + "top_p": { + "description": "核采样参数", + "type": "number" + } + } + }, "request.DataSource": { "type": "object", "properties": { @@ -8049,6 +8863,41 @@ const docTemplate = `{ } } }, + "request.ExportVersionRequest": { + "type": "object", + "required": [ + "versionCode", + "versionName" + ], + "properties": { + "apiIds": { + "description": "选中的API ID列表", + "type": "array", + "items": { + "type": "integer" + } + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "menuIds": { + "description": "选中的菜单ID列表", + "type": "array", + "items": { + "type": "integer" + } + }, + "versionCode": { + "description": "版本号", + "type": "string" + }, + "versionName": { + "description": "版本名称", + "type": "string" + } + } + }, "request.GetAuthorityId": { "type": "object", "properties": { @@ -8107,6 +8956,36 @@ const docTemplate = `{ } } }, + "request.ImportVersionRequest": { + "type": "object", + "required": [ + "version" + ], + "properties": { + "apis": { + "description": "API数据,直接复用SysApi", + "type": "array", + "items": { + "$ref": "#/definitions/system.SysApi" + } + }, + "menus": { + "description": "菜单数据,直接复用SysBaseMenu", + "type": "array", + "items": { + "$ref": "#/definitions/system.SysBaseMenu" + } + }, + "version": { + "description": "版本信息", + "allOf": [ + { + "$ref": "#/definitions/request.VersionInfo" + } + ] + } + } + }, "request.InitDB": { "type": "object", "required": [ @@ -8172,6 +9051,23 @@ const docTemplate = `{ } } }, + "request.Message": { + "type": "object", + "required": [ + "content", + "role" + ], + "properties": { + "content": { + "description": "消息内容", + "type": "string" + }, + "role": { + "description": "角色: system, user, assistant", + "type": "string" + } + } + }, "request.PageInfo": { "type": "object", "properties": { @@ -8307,6 +9203,18 @@ const docTemplate = `{ } } }, + "request.StopRequest": { + "type": "object", + "required": [ + "request_id" + ], + "properties": { + "request_id": { + "description": "要停止的请求ID", + "type": "string" + } + } + }, "request.SysAuthorityBtnReq": { "type": "object", "properties": { @@ -8366,6 +9274,121 @@ const docTemplate = `{ } } }, + "request.VersionInfo": { + "type": "object", + "required": [ + "code", + "name" + ], + "properties": { + "code": { + "description": "版本号", + "type": "string" + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "exportTime": { + "description": "导出时间", + "type": "string" + }, + "name": { + "description": "版本名称", + "type": "string" + } + } + }, + "response.APIError": { + "type": "object", + "properties": { + "code": { + "description": "错误代码", + "type": "string" + }, + "message": { + "description": "错误消息", + "type": "string" + }, + "type": { + "description": "错误类型", + "type": "string" + } + } + }, + "response.ChatResponse": { + "type": "object", + "properties": { + "choices": { + "description": "响应选择列表", + "type": "array", + "items": { + "$ref": "#/definitions/response.Choice" + } + }, + "created": { + "description": "创建时间戳", + "type": "integer" + }, + "error": { + "description": "错误信息", + "allOf": [ + { + "$ref": "#/definitions/response.APIError" + } + ] + }, + "id": { + "description": "响应ID", + "type": "string" + }, + "model": { + "description": "使用的模型", + "type": "string" + }, + "object": { + "description": "对象类型: chat.completion 或 chat.completion.chunk", + "type": "string" + }, + "usage": { + "description": "使用量统计(非流式响应)", + "allOf": [ + { + "$ref": "#/definitions/response.Usage" + } + ] + } + } + }, + "response.Choice": { + "type": "object", + "properties": { + "delta": { + "description": "增量消息(流式)", + "allOf": [ + { + "$ref": "#/definitions/response.Message" + } + ] + }, + "finish_reason": { + "description": "结束原因: stop, length, content_filter", + "type": "string" + }, + "index": { + "description": "选择索引", + "type": "integer" + }, + "message": { + "description": "完整响应消息(非流式)", + "allOf": [ + { + "$ref": "#/definitions/response.Message" + } + ] + } + } + }, "response.Email": { "type": "object", "properties": { @@ -8429,6 +9452,19 @@ const docTemplate = `{ } } }, + "response.Message": { + "type": "object", + "properties": { + "content": { + "description": "消息内容", + "type": "string" + }, + "role": { + "description": "角色: system, user, assistant", + "type": "string" + } + } + }, "response.PageResult": { "type": "object", "properties": { @@ -8467,6 +9503,27 @@ const docTemplate = `{ } } }, + "response.StopResponse": { + "type": "object", + "properties": { + "message": { + "description": "响应消息", + "type": "string" + }, + "request_id": { + "description": "请求ID", + "type": "string" + }, + "stopped_at": { + "description": "停止时间戳", + "type": "integer" + }, + "success": { + "description": "是否成功停止", + "type": "boolean" + } + } + }, "response.SysAPIListResponse": { "type": "object", "properties": { @@ -8580,6 +9637,23 @@ const docTemplate = `{ } } }, + "response.Usage": { + "type": "object", + "properties": { + "completion_tokens": { + "description": "输出token数", + "type": "integer" + }, + "prompt_tokens": { + "description": "输入token数", + "type": "integer" + }, + "total_tokens": { + "description": "总token数", + "type": "integer" + } + } + }, "system.Condition": { "type": "object", "properties": { @@ -8663,6 +9737,10 @@ const docTemplate = `{ "title": { "description": "菜单名", "type": "string" + }, + "transitionType": { + "description": "路由切换动画", + "type": "string" } } }, @@ -9267,6 +10345,43 @@ const docTemplate = `{ } } }, + "system.SysVersion": { + "type": "object", + "required": [ + "versionCode", + "versionName" + ], + "properties": { + "ID": { + "description": "主键ID", + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + }, + "versionCode": { + "description": "版本号", + "type": "string" + }, + "versionData": { + "description": "版本数据", + "type": "string" + }, + "versionName": { + "description": "版本名称", + "type": "string" + } + } + }, "system.System": { "type": "object", "properties": { @@ -9304,6 +10419,8 @@ var SwaggerInfo = &swag.Spec{ Description: "使用gin+vue进行极速开发的全栈开发基础平台", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", } func init() { diff --git a/server/docs/swagger.json b/server/docs/swagger.json index 9eb3da45..68338a9f 100644 --- a/server/docs/swagger.json +++ b/server/docs/swagger.json @@ -4,7 +4,7 @@ "description": "使用gin+vue进行极速开发的全栈开发基础平台", "title": "Gin-Vue-Admin Swagger API接口文档", "contact": {}, - "version": "v2.7.9-beta" + "version": "v2.8.4" }, "paths": { "/api/createApi": { @@ -1797,9 +1797,7 @@ "properties": { "data": { "type": "array", - "items": { - "type": "object" - } + "items": {} }, "msg": { "type": "string" @@ -1812,6 +1810,120 @@ } } }, + "/autoCode/mcp": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "自动McpTool", + "parameters": [ + { + "description": "创建自动代码", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AutoMcpTool" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"创建成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/autoCode/mcpList": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "自动McpTool", + "parameters": [ + { + "description": "创建自动代码", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AutoMcpTool" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"创建成功\"}", + "schema": { + "type": "string" + } + } + } + } + }, + "/autoCode/mcpTest": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "mcp" + ], + "summary": "测试McpTool", + "parameters": [ + { + "description": "调用MCP Tool的参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "type": "object" + } + } + ], + "responses": { + "200": { + "description": "{\"success\":true,\"data\":{},\"msg\":\"测试成功\"}", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/autoCode/preview": { "post": { "security": [ @@ -4568,26 +4680,6 @@ } } }, - "/sysExportTemplate/ExportTemplate": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SysExportTemplate" - ], - "summary": "导出表格模板", - "responses": {} - } - }, "/sysExportTemplate/createSysExportTemplate": { "post": { "security": [ @@ -4722,6 +4814,66 @@ "responses": {} } }, + "/sysExportTemplate/exportExcelByToken": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExportExcelByToken" + ], + "summary": "导出表格", + "responses": {} + } + }, + "/sysExportTemplate/exportTemplate": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysExportTemplate" + ], + "summary": "导出表格模板", + "responses": {} + } + }, + "/sysExportTemplate/exportTemplateByToken": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExportTemplateByToken" + ], + "summary": "通过token导出表格模板", + "responses": {} + } + }, "/sysExportTemplate/findSysExportTemplate": { "get": { "security": [ @@ -4982,56 +5134,6 @@ } } }, - "/sysOperationRecord/createSysOperationRecord": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SysOperationRecord" - ], - "summary": "创建SysOperationRecord", - "parameters": [ - { - "description": "创建SysOperationRecord", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/system.SysOperationRecord" - } - } - ], - "responses": { - "200": { - "description": "创建SysOperationRecord", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.Response" - }, - { - "type": "object", - "properties": { - "msg": { - "type": "string" - } - } - } - ] - } - } - } - } - }, "/sysOperationRecord/deleteSysOperationRecord": { "delete": { "security": [ @@ -5806,6 +5908,415 @@ } } }, + "/sysVersion/deleteSysVersion": { + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "删除版本管理", + "parameters": [ + { + "description": "删除版本管理", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysVersion" + } + } + ], + "responses": { + "200": { + "description": "删除成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/deleteSysVersionByIds": { + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "批量删除版本管理", + "responses": { + "200": { + "description": "批量删除成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/downloadVersionJson": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "下载版本JSON数据", + "parameters": [ + { + "type": "string", + "description": "版本ID", + "name": "ID", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "下载成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/exportVersion": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "创建发版数据", + "parameters": [ + { + "description": "创建发版数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ExportVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "创建成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/findSysVersion": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "用id查询版本管理", + "parameters": [ + { + "type": "integer", + "description": "用id查询版本管理", + "name": "ID", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "查询成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysVersion" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/getSysVersionList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "分页获取版本管理列表", + "parameters": [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "name": "createdAtRange", + "in": "query" + }, + { + "type": "string", + "description": "关键字", + "name": "keyword", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "name": "versionCode", + "in": "query" + }, + { + "type": "string", + "name": "versionName", + "in": "query" + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.PageResult" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/getSysVersionPublic": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "不需要鉴权的版本管理接口", + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysVersion/importVersion": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysVersion" + ], + "summary": "导入版本数据", + "parameters": [ + { + "description": "版本JSON数据", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ImportVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "导入成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/system/getServerInfo": { "post": { "security": [ @@ -5898,10 +6409,10 @@ "tags": [ "System" ], - "summary": "重启系统", + "summary": "重载系统", "responses": { "200": { - "description": "重启系统", + "description": "重载系统", "schema": { "allOf": [ { @@ -6515,6 +7026,142 @@ } } } + }, + "/volcengine/llm/chat": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "LLM聊天完成", + "parameters": [ + { + "description": "聊天请求参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ChatRequest" + } + } + ], + "responses": { + "200": { + "description": "聊天响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.ChatResponse" + } + } + } + ] + } + } + } + } + }, + "/volcengine/llm/sessions": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "获取活跃会话数量", + "responses": { + "200": { + "description": "活跃会话数量", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "integer" + } + } + } + ] + } + } + } + } + }, + "/volcengine/llm/stop": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Volcengine" + ], + "summary": "停止LLM生成", + "parameters": [ + { + "description": "停止请求参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.StopRequest" + } + } + ], + "responses": { + "200": { + "description": "停止响应", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.StopResponse" + } + } + } + ] + } + } + } + } } }, "definitions": { @@ -6647,7 +7294,7 @@ "type": "integer" }, "open-captcha": { - "description": "防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码此数,如3代表错误三次后出现验证码", + "description": "防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码次数,如3代表错误三次后出现验证码", "type": "integer" }, "open-captcha-timeout": { @@ -6749,6 +7396,31 @@ } } }, + "config.MCP": { + "type": "object", + "properties": { + "message_path": { + "description": "消息路径", + "type": "string" + }, + "name": { + "description": "MCP名称", + "type": "string" + }, + "sse_path": { + "description": "SSE路径", + "type": "string" + }, + "url_prefix": { + "description": "URL前缀", + "type": "string" + }, + "version": { + "description": "MCP版本", + "type": "string" + } + } + }, "config.Minio": { "type": "object", "properties": { @@ -7204,6 +7876,14 @@ } ] }, + "mcp": { + "description": "MCP配置", + "allOf": [ + { + "$ref": "#/definitions/config.MCP" + } + ] + }, "minio": { "$ref": "#/definitions/config.Minio" }, @@ -7248,6 +7928,14 @@ "tencent-cos": { "$ref": "#/definitions/config.TencentCOS" }, + "volcengine": { + "description": "Volcengine配置", + "allOf": [ + { + "$ref": "#/definitions/config.Volcengine" + } + ] + }, "zap": { "$ref": "#/definitions/config.Zap" } @@ -7443,6 +8131,31 @@ } } }, + "config.Volcengine": { + "type": "object", + "properties": { + "access-key": { + "description": "火山引擎访问密钥ID", + "type": "string" + }, + "default-model": { + "description": "默认模型ID,如:ep-xxx", + "type": "string" + }, + "endpoint": { + "description": "服务端点,如:https://ark.cn-beijing.volces.com", + "type": "string" + }, + "region": { + "description": "区域,如:cn-beijing", + "type": "string" + }, + "secret-key": { + "description": "火山引擎访问密钥Secret", + "type": "string" + } + } + }, "config.Zap": { "type": "object", "properties": { @@ -7666,6 +8379,10 @@ "description": "服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议", "type": "string" }, + "is-loginauth": { + "description": "是否LoginAuth 是否使用LoginAuth认证方式(适用于IBM、微软邮箱服务器等)", + "type": "boolean" + }, "is-ssl": { "description": "是否SSL 是否开启SSL", "type": "boolean" @@ -7952,6 +8669,65 @@ } } }, + "request.AutoMcpTool": { + "type": "object", + "required": [ + "description", + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "array", + "items": { + "type": "object", + "required": [ + "description", + "name", + "type" + ], + "properties": { + "default": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "type": { + "description": "string, number, boolean, object, array", + "type": "string" + } + } + } + }, + "response": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "text, image", + "type": "string" + } + } + } + } + } + }, "request.CasbinInReceive": { "type": "object", "properties": { @@ -7993,6 +8769,45 @@ } } }, + "request.ChatRequest": { + "type": "object", + "required": [ + "messages" + ], + "properties": { + "max_tokens": { + "description": "最大生成token数", + "type": "integer" + }, + "messages": { + "description": "对话消息列表", + "type": "array", + "items": { + "$ref": "#/definitions/request.Message" + } + }, + "model": { + "description": "模型名称,如果为空则使用默认模型", + "type": "string" + }, + "request_id": { + "description": "请求ID,用于流式响应管理", + "type": "string" + }, + "stream": { + "description": "是否流式响应,默认false", + "type": "boolean" + }, + "temperature": { + "description": "温度参数,控制随机性,范围0-1", + "type": "number" + }, + "top_p": { + "description": "核采样参数", + "type": "number" + } + } + }, "request.DataSource": { "type": "object", "properties": { @@ -8040,6 +8855,41 @@ } } }, + "request.ExportVersionRequest": { + "type": "object", + "required": [ + "versionCode", + "versionName" + ], + "properties": { + "apiIds": { + "description": "选中的API ID列表", + "type": "array", + "items": { + "type": "integer" + } + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "menuIds": { + "description": "选中的菜单ID列表", + "type": "array", + "items": { + "type": "integer" + } + }, + "versionCode": { + "description": "版本号", + "type": "string" + }, + "versionName": { + "description": "版本名称", + "type": "string" + } + } + }, "request.GetAuthorityId": { "type": "object", "properties": { @@ -8098,6 +8948,36 @@ } } }, + "request.ImportVersionRequest": { + "type": "object", + "required": [ + "version" + ], + "properties": { + "apis": { + "description": "API数据,直接复用SysApi", + "type": "array", + "items": { + "$ref": "#/definitions/system.SysApi" + } + }, + "menus": { + "description": "菜单数据,直接复用SysBaseMenu", + "type": "array", + "items": { + "$ref": "#/definitions/system.SysBaseMenu" + } + }, + "version": { + "description": "版本信息", + "allOf": [ + { + "$ref": "#/definitions/request.VersionInfo" + } + ] + } + } + }, "request.InitDB": { "type": "object", "required": [ @@ -8163,6 +9043,23 @@ } } }, + "request.Message": { + "type": "object", + "required": [ + "content", + "role" + ], + "properties": { + "content": { + "description": "消息内容", + "type": "string" + }, + "role": { + "description": "角色: system, user, assistant", + "type": "string" + } + } + }, "request.PageInfo": { "type": "object", "properties": { @@ -8298,6 +9195,18 @@ } } }, + "request.StopRequest": { + "type": "object", + "required": [ + "request_id" + ], + "properties": { + "request_id": { + "description": "要停止的请求ID", + "type": "string" + } + } + }, "request.SysAuthorityBtnReq": { "type": "object", "properties": { @@ -8357,6 +9266,121 @@ } } }, + "request.VersionInfo": { + "type": "object", + "required": [ + "code", + "name" + ], + "properties": { + "code": { + "description": "版本号", + "type": "string" + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "exportTime": { + "description": "导出时间", + "type": "string" + }, + "name": { + "description": "版本名称", + "type": "string" + } + } + }, + "response.APIError": { + "type": "object", + "properties": { + "code": { + "description": "错误代码", + "type": "string" + }, + "message": { + "description": "错误消息", + "type": "string" + }, + "type": { + "description": "错误类型", + "type": "string" + } + } + }, + "response.ChatResponse": { + "type": "object", + "properties": { + "choices": { + "description": "响应选择列表", + "type": "array", + "items": { + "$ref": "#/definitions/response.Choice" + } + }, + "created": { + "description": "创建时间戳", + "type": "integer" + }, + "error": { + "description": "错误信息", + "allOf": [ + { + "$ref": "#/definitions/response.APIError" + } + ] + }, + "id": { + "description": "响应ID", + "type": "string" + }, + "model": { + "description": "使用的模型", + "type": "string" + }, + "object": { + "description": "对象类型: chat.completion 或 chat.completion.chunk", + "type": "string" + }, + "usage": { + "description": "使用量统计(非流式响应)", + "allOf": [ + { + "$ref": "#/definitions/response.Usage" + } + ] + } + } + }, + "response.Choice": { + "type": "object", + "properties": { + "delta": { + "description": "增量消息(流式)", + "allOf": [ + { + "$ref": "#/definitions/response.Message" + } + ] + }, + "finish_reason": { + "description": "结束原因: stop, length, content_filter", + "type": "string" + }, + "index": { + "description": "选择索引", + "type": "integer" + }, + "message": { + "description": "完整响应消息(非流式)", + "allOf": [ + { + "$ref": "#/definitions/response.Message" + } + ] + } + } + }, "response.Email": { "type": "object", "properties": { @@ -8420,6 +9444,19 @@ } } }, + "response.Message": { + "type": "object", + "properties": { + "content": { + "description": "消息内容", + "type": "string" + }, + "role": { + "description": "角色: system, user, assistant", + "type": "string" + } + } + }, "response.PageResult": { "type": "object", "properties": { @@ -8458,6 +9495,27 @@ } } }, + "response.StopResponse": { + "type": "object", + "properties": { + "message": { + "description": "响应消息", + "type": "string" + }, + "request_id": { + "description": "请求ID", + "type": "string" + }, + "stopped_at": { + "description": "停止时间戳", + "type": "integer" + }, + "success": { + "description": "是否成功停止", + "type": "boolean" + } + } + }, "response.SysAPIListResponse": { "type": "object", "properties": { @@ -8571,6 +9629,23 @@ } } }, + "response.Usage": { + "type": "object", + "properties": { + "completion_tokens": { + "description": "输出token数", + "type": "integer" + }, + "prompt_tokens": { + "description": "输入token数", + "type": "integer" + }, + "total_tokens": { + "description": "总token数", + "type": "integer" + } + } + }, "system.Condition": { "type": "object", "properties": { @@ -8654,6 +9729,10 @@ "title": { "description": "菜单名", "type": "string" + }, + "transitionType": { + "description": "路由切换动画", + "type": "string" } } }, @@ -9258,6 +10337,43 @@ } } }, + "system.SysVersion": { + "type": "object", + "required": [ + "versionCode", + "versionName" + ], + "properties": { + "ID": { + "description": "主键ID", + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "版本描述", + "type": "string" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + }, + "versionCode": { + "description": "版本号", + "type": "string" + }, + "versionData": { + "description": "版本数据", + "type": "string" + }, + "versionName": { + "description": "版本名称", + "type": "string" + } + } + }, "system.System": { "type": "object", "properties": { diff --git a/server/docs/swagger.yaml b/server/docs/swagger.yaml index 1a1f8cc7..863fad2e 100644 --- a/server/docs/swagger.yaml +++ b/server/docs/swagger.yaml @@ -85,7 +85,7 @@ definitions: description: 验证码长度 type: integer open-captcha: - description: 防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码此数,如3代表错误三次后出现验证码 + description: 防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码次数,如3代表错误三次后出现验证码 type: integer open-captcha-timeout: description: 防爆破验证码超时时间,单位:s(秒) @@ -153,6 +153,24 @@ definitions: description: 本地文件存储路径 type: string type: object + config.MCP: + properties: + message_path: + description: 消息路径 + type: string + name: + description: MCP名称 + type: string + sse_path: + description: SSE路径 + type: string + url_prefix: + description: URL前缀 + type: string + version: + description: MCP版本 + type: string + type: object config.Minio: properties: access-key-id: @@ -477,6 +495,10 @@ definitions: allOf: - $ref: '#/definitions/config.Local' description: oss + mcp: + allOf: + - $ref: '#/definitions/config.MCP' + description: MCP配置 minio: $ref: '#/definitions/config.Minio' mongo: @@ -505,6 +527,10 @@ definitions: $ref: '#/definitions/config.System' tencent-cos: $ref: '#/definitions/config.TencentCOS' + volcengine: + allOf: + - $ref: '#/definitions/config.Volcengine' + description: Volcengine配置 zap: $ref: '#/definitions/config.Zap' type: object @@ -645,6 +671,24 @@ definitions: secret-key: type: string type: object + config.Volcengine: + properties: + access-key: + description: 火山引擎访问密钥ID + type: string + default-model: + description: 默认模型ID,如:ep-xxx + type: string + endpoint: + description: 服务端点,如:https://ark.cn-beijing.volces.com + type: string + region: + description: 区域,如:cn-beijing + type: string + secret-key: + description: 火山引擎访问密钥Secret + type: string + type: object config.Zap: properties: director: @@ -802,6 +846,9 @@ definitions: host: description: 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 type: string + is-loginauth: + description: 是否LoginAuth 是否使用LoginAuth认证方式(适用于IBM、微软邮箱服务器等) + type: boolean is-ssl: description: 是否SSL 是否开启SSL type: boolean @@ -1014,6 +1061,46 @@ definitions: description: 是否前端表格列 type: boolean type: object + request.AutoMcpTool: + properties: + description: + type: string + name: + type: string + params: + items: + properties: + default: + type: string + description: + type: string + name: + type: string + required: + type: boolean + type: + description: string, number, boolean, object, array + type: string + required: + - description + - name + - type + type: object + type: array + response: + items: + properties: + type: + description: text, image + type: string + required: + - type + type: object + type: array + required: + - description + - name + type: object request.CasbinInReceive: properties: authorityId: @@ -1042,6 +1129,34 @@ definitions: description: 密码 type: string type: object + request.ChatRequest: + properties: + max_tokens: + description: 最大生成token数 + type: integer + messages: + description: 对话消息列表 + items: + $ref: '#/definitions/request.Message' + type: array + model: + description: 模型名称,如果为空则使用默认模型 + type: string + request_id: + description: 请求ID,用于流式响应管理 + type: string + stream: + description: 是否流式响应,默认false + type: boolean + temperature: + description: 温度参数,控制随机性,范围0-1 + type: number + top_p: + description: 核采样参数 + type: number + required: + - messages + type: object request.DataSource: properties: association: @@ -1074,6 +1189,31 @@ definitions: description: 每页大小 type: integer type: object + request.ExportVersionRequest: + properties: + apiIds: + description: 选中的API ID列表 + items: + type: integer + type: array + description: + description: 版本描述 + type: string + menuIds: + description: 选中的菜单ID列表 + items: + type: integer + type: array + versionCode: + description: 版本号 + type: string + versionName: + description: 版本名称 + type: string + required: + - versionCode + - versionName + type: object request.GetAuthorityId: properties: authorityId: @@ -1113,6 +1253,25 @@ definitions: type: integer type: array type: object + request.ImportVersionRequest: + properties: + apis: + description: API数据,直接复用SysApi + items: + $ref: '#/definitions/system.SysApi' + type: array + menus: + description: 菜单数据,直接复用SysBaseMenu + items: + $ref: '#/definitions/system.SysBaseMenu' + type: array + version: + allOf: + - $ref: '#/definitions/request.VersionInfo' + description: 版本信息 + required: + - version + type: object request.InitDB: properties: adminPassword: @@ -1160,6 +1319,18 @@ definitions: description: 用户名 type: string type: object + request.Message: + properties: + content: + description: 消息内容 + type: string + role: + description: '角色: system, user, assistant' + type: string + required: + - content + - role + type: object request.PageInfo: properties: keyword: @@ -1257,6 +1428,14 @@ definitions: id: type: integer type: object + request.StopRequest: + properties: + request_id: + description: 要停止的请求ID + type: string + required: + - request_id + type: object request.SysAuthorityBtnReq: properties: authorityId: @@ -1298,6 +1477,81 @@ definitions: description: 主键ID type: integer type: object + request.VersionInfo: + properties: + code: + description: 版本号 + type: string + description: + description: 版本描述 + type: string + exportTime: + description: 导出时间 + type: string + name: + description: 版本名称 + type: string + required: + - code + - name + type: object + response.APIError: + properties: + code: + description: 错误代码 + type: string + message: + description: 错误消息 + type: string + type: + description: 错误类型 + type: string + type: object + response.ChatResponse: + properties: + choices: + description: 响应选择列表 + items: + $ref: '#/definitions/response.Choice' + type: array + created: + description: 创建时间戳 + type: integer + error: + allOf: + - $ref: '#/definitions/response.APIError' + description: 错误信息 + id: + description: 响应ID + type: string + model: + description: 使用的模型 + type: string + object: + description: '对象类型: chat.completion 或 chat.completion.chunk' + type: string + usage: + allOf: + - $ref: '#/definitions/response.Usage' + description: 使用量统计(非流式响应) + type: object + response.Choice: + properties: + delta: + allOf: + - $ref: '#/definitions/response.Message' + description: 增量消息(流式) + finish_reason: + description: '结束原因: stop, length, content_filter' + type: string + index: + description: 选择索引 + type: integer + message: + allOf: + - $ref: '#/definitions/response.Message' + description: 完整响应消息(非流式) + type: object response.Email: properties: body: @@ -1339,6 +1593,15 @@ definitions: user: $ref: '#/definitions/system.SysUser' type: object + response.Message: + properties: + content: + description: 消息内容 + type: string + role: + description: '角色: system, user, assistant' + type: string + type: object response.PageResult: properties: list: {} @@ -1364,6 +1627,21 @@ definitions: msg: type: string type: object + response.StopResponse: + properties: + message: + description: 响应消息 + type: string + request_id: + description: 请求ID + type: string + stopped_at: + description: 停止时间戳 + type: integer + success: + description: 是否成功停止 + type: boolean + type: object response.SysAPIListResponse: properties: apis: @@ -1436,6 +1714,18 @@ definitions: user: $ref: '#/definitions/system.SysUser' type: object + response.Usage: + properties: + completion_tokens: + description: 输出token数 + type: integer + prompt_tokens: + description: 输入token数 + type: integer + total_tokens: + description: 总token数 + type: integer + type: object system.Condition: properties: ID: @@ -1495,6 +1785,9 @@ definitions: title: description: 菜单名 type: string + transitionType: + description: 路由切换动画 + type: string type: object system.SysApi: properties: @@ -1920,6 +2213,33 @@ definitions: description: 用户UUID type: string type: object + system.SysVersion: + properties: + ID: + description: 主键ID + type: integer + createdAt: + description: 创建时间 + type: string + description: + description: 版本描述 + type: string + updatedAt: + description: 更新时间 + type: string + versionCode: + description: 版本号 + type: string + versionData: + description: 版本数据 + type: string + versionName: + description: 版本名称 + type: string + required: + - versionCode + - versionName + type: object system.System: properties: config: @@ -1929,7 +2249,7 @@ info: contact: {} description: 使用gin+vue进行极速开发的全栈开发基础平台 title: Gin-Vue-Admin Swagger API接口文档 - version: v2.7.9-beta + version: v2.8.4 paths: /api/createApi: post: @@ -2935,8 +3255,7 @@ paths: - $ref: '#/definitions/response.Response' - properties: data: - items: - type: object + items: {} type: array msg: type: string @@ -2946,6 +3265,75 @@ paths: summary: 安装插件 tags: - AutoCodePlugin + /autoCode/mcp: + post: + consumes: + - application/json + parameters: + - description: 创建自动代码 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.AutoMcpTool' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"创建成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 自动McpTool + tags: + - mcp + /autoCode/mcpList: + post: + consumes: + - application/json + parameters: + - description: 创建自动代码 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.AutoMcpTool' + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"创建成功"}' + schema: + type: string + security: + - ApiKeyAuth: [] + summary: 自动McpTool + tags: + - mcp + /autoCode/mcpTest: + post: + consumes: + - application/json + parameters: + - description: 调用MCP Tool的参数 + in: body + name: data + required: true + schema: + type: object + produces: + - application/json + responses: + "200": + description: '{"success":true,"data":{},"msg":"测试成功"}' + schema: + $ref: '#/definitions/response.Response' + security: + - ApiKeyAuth: [] + summary: 测试McpTool + tags: + - mcp /autoCode/preview: post: consumes: @@ -4525,18 +4913,6 @@ paths: summary: 更新SysDictionaryDetail tags: - SysDictionaryDetail - /sysExportTemplate/ExportTemplate: - get: - consumes: - - application/json - produces: - - application/json - responses: {} - security: - - ApiKeyAuth: [] - summary: 导出表格模板 - tags: - - SysExportTemplate /sysExportTemplate/createSysExportTemplate: post: consumes: @@ -4618,6 +4994,42 @@ paths: summary: 导出表格 tags: - SysExportTemplate + /sysExportTemplate/exportExcelByToken: + get: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - ApiKeyAuth: [] + summary: 导出表格 + tags: + - ExportExcelByToken + /sysExportTemplate/exportTemplate: + get: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - ApiKeyAuth: [] + summary: 导出表格模板 + tags: + - SysExportTemplate + /sysExportTemplate/exportTemplateByToken: + get: + consumes: + - application/json + produces: + - application/json + responses: {} + security: + - ApiKeyAuth: [] + summary: 通过token导出表格模板 + tags: + - ExportTemplateByToken /sysExportTemplate/findSysExportTemplate: get: consumes: @@ -4781,34 +5193,6 @@ paths: summary: 更新导出模板 tags: - SysExportTemplate - /sysOperationRecord/createSysOperationRecord: - post: - consumes: - - application/json - parameters: - - description: 创建SysOperationRecord - in: body - name: data - required: true - schema: - $ref: '#/definitions/system.SysOperationRecord' - produces: - - application/json - responses: - "200": - description: 创建SysOperationRecord - schema: - allOf: - - $ref: '#/definitions/response.Response' - - properties: - msg: - type: string - type: object - security: - - ApiKeyAuth: [] - summary: 创建SysOperationRecord - tags: - - SysOperationRecord /sysOperationRecord/deleteSysOperationRecord: delete: consumes: @@ -5267,6 +5651,238 @@ paths: summary: 更新参数 tags: - SysParams + /sysVersion/deleteSysVersion: + delete: + consumes: + - application/json + parameters: + - description: 删除版本管理 + in: body + name: data + required: true + schema: + $ref: '#/definitions/system.SysVersion' + produces: + - application/json + responses: + "200": + description: 删除成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 删除版本管理 + tags: + - SysVersion + /sysVersion/deleteSysVersionByIds: + delete: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: 批量删除成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 批量删除版本管理 + tags: + - SysVersion + /sysVersion/downloadVersionJson: + get: + consumes: + - application/json + parameters: + - description: 版本ID + in: query + name: ID + required: true + type: string + produces: + - application/json + responses: + "200": + description: 下载成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + type: object + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 下载版本JSON数据 + tags: + - SysVersion + /sysVersion/exportVersion: + post: + consumes: + - application/json + parameters: + - description: 创建发版数据 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.ExportVersionRequest' + produces: + - application/json + responses: + "200": + description: 创建成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 创建发版数据 + tags: + - SysVersion + /sysVersion/findSysVersion: + get: + consumes: + - application/json + parameters: + - description: 用id查询版本管理 + in: query + name: ID + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 查询成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/system.SysVersion' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 用id查询版本管理 + tags: + - SysVersion + /sysVersion/getSysVersionList: + get: + consumes: + - application/json + parameters: + - collectionFormat: csv + in: query + items: + type: string + name: createdAtRange + type: array + - description: 关键字 + in: query + name: keyword + type: string + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - in: query + name: versionCode + type: string + - in: query + name: versionName + type: string + produces: + - application/json + responses: + "200": + description: 获取成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/response.PageResult' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 分页获取版本管理列表 + tags: + - SysVersion + /sysVersion/getSysVersionPublic: + get: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: 获取成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + type: object + msg: + type: string + type: object + summary: 不需要鉴权的版本管理接口 + tags: + - SysVersion + /sysVersion/importVersion: + post: + consumes: + - application/json + parameters: + - description: 版本JSON数据 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.ImportVersionRequest' + produces: + - application/json + responses: + "200": + description: 导入成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 导入版本数据 + tags: + - SysVersion /system/getServerInfo: post: produces: @@ -5316,7 +5932,7 @@ paths: - application/json responses: "200": - description: 重启系统 + description: 重载系统 schema: allOf: - $ref: '#/definitions/response.Response' @@ -5326,7 +5942,7 @@ paths: type: object security: - ApiKeyAuth: [] - summary: 重启系统 + summary: 重载系统 tags: - System /system/setSystemConfig: @@ -5665,6 +6281,81 @@ paths: summary: 设置用户信息 tags: - SysUser + /volcengine/llm/chat: + post: + consumes: + - application/json + parameters: + - description: 聊天请求参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.ChatRequest' + produces: + - application/json + responses: + "200": + description: 聊天响应 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/response.ChatResponse' + type: object + security: + - ApiKeyAuth: [] + summary: LLM聊天完成 + tags: + - Volcengine + /volcengine/llm/sessions: + get: + produces: + - application/json + responses: + "200": + description: 活跃会话数量 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + type: integer + type: object + security: + - ApiKeyAuth: [] + summary: 获取活跃会话数量 + tags: + - Volcengine + /volcengine/llm/stop: + post: + consumes: + - application/json + parameters: + - description: 停止请求参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/request.StopRequest' + produces: + - application/json + responses: + "200": + description: 停止响应 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/response.StopResponse' + type: object + security: + - ApiKeyAuth: [] + summary: 停止LLM生成 + tags: + - Volcengine securityDefinitions: ApiKeyAuth: in: header diff --git a/server/go.mod b/server/go.mod index 8a313c48..181f8573 100644 --- a/server/go.mod +++ b/server/go.mod @@ -149,6 +149,8 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/ulikunitz/xz v0.5.12 // indirect + github.com/volcengine/volc-sdk-golang v1.0.23 // indirect + github.com/volcengine/volcengine-go-sdk v1.1.25 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect @@ -170,6 +172,7 @@ require ( golang.org/x/tools v0.29.0 // indirect google.golang.org/protobuf v1.36.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/hints v1.1.2 // indirect gorm.io/plugin/dbresolver v1.5.3 // indirect diff --git a/server/go.sum b/server/go.sum index 8dfab999..03dcbec1 100644 --- a/server/go.sum +++ b/server/go.sum @@ -54,6 +54,7 @@ github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= @@ -190,6 +191,13 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -198,6 +206,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -288,6 +297,7 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -429,6 +439,7 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -464,6 +475,10 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/unrolled/secure v1.17.0 h1:Io7ifFgo99Bnh0J7+Q+qcMzWM6kaDPCA5FroFZEdbWU= github.com/unrolled/secure v1.17.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= +github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8= +github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= +github.com/volcengine/volcengine-go-sdk v1.1.25 h1:wwR2DTJGw2sOZ1wTWaQLn03PGO0O+motGvsoVvAp5Zk= +github.com/volcengine/volcengine-go-sdk v1.1.25/go.mod h1:EyKoi6t6eZxoPNGr2GdFCZti2Skd7MO3eUzx7TtSvNo= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= @@ -744,6 +759,7 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -751,10 +767,20 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= diff --git a/server/initialize/plugin_biz_v1.go b/server/initialize/plugin_biz_v1.go index 1585db35..a921dca6 100644 --- a/server/initialize/plugin_biz_v1.go +++ b/server/initialize/plugin_biz_v1.go @@ -5,6 +5,7 @@ import ( "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/plugin/email" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/volcengine" "github.com/flipped-aurora/gin-vue-admin/server/utils/plugin" "github.com/gin-gonic/gin" ) @@ -22,15 +23,18 @@ func bizPluginV1(group ...*gin.RouterGroup) { private := group[0] public := group[1] // 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同 - PluginInit(private, email.CreateEmailPlug( - global.GVA_CONFIG.Email.To, - global.GVA_CONFIG.Email.From, - global.GVA_CONFIG.Email.Host, - global.GVA_CONFIG.Email.Secret, - global.GVA_CONFIG.Email.Nickname, - global.GVA_CONFIG.Email.Port, - global.GVA_CONFIG.Email.IsSSL, - global.GVA_CONFIG.Email.IsLoginAuth, - )) + PluginInit(private, + email.CreateEmailPlug( + global.GVA_CONFIG.Email.To, + global.GVA_CONFIG.Email.From, + global.GVA_CONFIG.Email.Host, + global.GVA_CONFIG.Email.Secret, + global.GVA_CONFIG.Email.Nickname, + global.GVA_CONFIG.Email.Port, + global.GVA_CONFIG.Email.IsSSL, + global.GVA_CONFIG.Email.IsLoginAuth, + ), + volcengine.CreateVolcenginePlug(), + ) holder(public, private) } diff --git a/server/plugin/volcengine/api/enter.go b/server/plugin/volcengine/api/enter.go new file mode 100644 index 00000000..d055a051 --- /dev/null +++ b/server/plugin/volcengine/api/enter.go @@ -0,0 +1,7 @@ +package api + +type ApiGroup struct { + LLMApi +} + +var ApiGroupApp = new(ApiGroup) diff --git a/server/plugin/volcengine/api/llm_api.go b/server/plugin/volcengine/api/llm_api.go new file mode 100644 index 00000000..ea820b05 --- /dev/null +++ b/server/plugin/volcengine/api/llm_api.go @@ -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) +} diff --git a/server/plugin/volcengine/main.go b/server/plugin/volcengine/main.go new file mode 100644 index 00000000..1225f93d --- /dev/null +++ b/server/plugin/volcengine/main.go @@ -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" +} diff --git a/server/plugin/volcengine/model/request/llm.go b/server/plugin/volcengine/model/request/llm.go new file mode 100644 index 00000000..81f2b0ea --- /dev/null +++ b/server/plugin/volcengine/model/request/llm.go @@ -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 +} diff --git a/server/plugin/volcengine/model/response/llm.go b/server/plugin/volcengine/model/response/llm.go new file mode 100644 index 00000000..3fe18594 --- /dev/null +++ b/server/plugin/volcengine/model/response/llm.go @@ -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 +} diff --git a/server/plugin/volcengine/router/enter.go b/server/plugin/volcengine/router/enter.go new file mode 100644 index 00000000..f60980d0 --- /dev/null +++ b/server/plugin/volcengine/router/enter.go @@ -0,0 +1,7 @@ +package router + +type RouterGroup struct { + LLMRouter +} + +var RouterGroupApp = new(RouterGroup) diff --git a/server/plugin/volcengine/router/llm_router.go b/server/plugin/volcengine/router/llm_router.go new file mode 100644 index 00000000..f4324a5b --- /dev/null +++ b/server/plugin/volcengine/router/llm_router.go @@ -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) // 获取活跃会话数量 + } +} diff --git a/server/plugin/volcengine/service/llm_service.go b/server/plugin/volcengine/service/llm_service.go new file mode 100644 index 00000000..f5cb713d --- /dev/null +++ b/server/plugin/volcengine/service/llm_service.go @@ -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 +}