feat: 新增业务字段路径读写工具
新增 TakeBusinessFields、WriteBusinessFields、SetByPath 与 GetByPath 等工具,支持按映射路径写入请求体与解析响应,并更新相关依赖。
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"model-gateway/consts/model"
|
||||
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type modelManageCol struct {
|
||||
beans.SQLBaseCol
|
||||
ModelSupplier string
|
||||
ModelName string
|
||||
ModelType string
|
||||
BaseURL string
|
||||
SystemModel string
|
||||
HttpMethod string
|
||||
ChatModel string
|
||||
ResponseType string
|
||||
ApiKey string
|
||||
Enabled string
|
||||
RequestHeadMapping string
|
||||
RequestBodyMapping string
|
||||
RequestBusinessFieldMapping string
|
||||
ResponseMapping string
|
||||
ResponseBodyMapping string
|
||||
ResponseBusinessFieldMapping string
|
||||
MaxConcurrency string
|
||||
TokenPredictPrice string
|
||||
TokenPredictPriceUnit string
|
||||
PriceConfig string
|
||||
MaxTokens string
|
||||
MinDuration string
|
||||
MaxDuration string
|
||||
LastFrame string
|
||||
}
|
||||
|
||||
var ModelManageCol = modelManageCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
ModelSupplier: "model_supplier",
|
||||
ModelName: "model_name",
|
||||
ModelType: "model_type",
|
||||
BaseURL: "base_url",
|
||||
SystemModel: "system_model",
|
||||
HttpMethod: "http_method",
|
||||
ChatModel: "chat_model",
|
||||
ResponseType: "response_type",
|
||||
ApiKey: "api_key",
|
||||
Enabled: "enabled",
|
||||
RequestHeadMapping: "request_head_mapping",
|
||||
RequestBodyMapping: "request_body_mapping",
|
||||
RequestBusinessFieldMapping: "request_business_field_mapping",
|
||||
ResponseMapping: "response_mapping",
|
||||
ResponseBodyMapping: "response_body_mapping",
|
||||
ResponseBusinessFieldMapping: "response_business_field_mapping",
|
||||
MaxConcurrency: "max_concurrency",
|
||||
TokenPredictPrice: "token_predict_price",
|
||||
TokenPredictPriceUnit: "token_predict_price_unit",
|
||||
PriceConfig: "price_config",
|
||||
MaxTokens: "max_tokens",
|
||||
MinDuration: "min_duration",
|
||||
MaxDuration: "max_duration",
|
||||
LastFrame: "last_frame",
|
||||
}
|
||||
|
||||
type ModelManage struct {
|
||||
beans.SQLBaseDO `orm:",inline"`
|
||||
ModelSupplier model.SupplierType `orm:"model_supplier" json:"modelSupplier" description:"模型供应商"`
|
||||
ModelName string `orm:"model_name" json:"modelName" description:"模型名称"`
|
||||
ModelType model.ModelType `orm:"model_type" json:"modelType" description:"模型类型"`
|
||||
BaseURL string `orm:"base_url" json:"baseUrl" description:"模型地址"`
|
||||
SystemModel *bool `orm:"system_model" json:"systemModel" description:"系统模型"`
|
||||
HttpMethod string `orm:"http_method" json:"httpMethod" description:"http方法"`
|
||||
ChatModel *bool `orm:"chat_model" json:"chatModel" description:"是否聊天模型"`
|
||||
ResponseType model.ResponseType `orm:"response_type" json:"responseType" description:"返回类型:1同步,2异步,3流"`
|
||||
ApiKey string `orm:"api_key" json:"apiKey" description:"api key"`
|
||||
Enabled *bool `orm:"enabled" json:"enabled" description:"是否启用"`
|
||||
RequestHeadMapping map[string]string `orm:"request_head_mapping" json:"requestHeadMapping" description:"请求头映射"`
|
||||
RequestBodyMapping map[string]any `orm:"request_body_mapping" json:"requestBodyMapping" description:"请求体映射"`
|
||||
RequestBusinessFieldMapping map[string]string `orm:"request_business_field_mapping" json:"requestBusinessFieldMapping" description:"请求业务字段映射"`
|
||||
ResponseMapping map[string]any `orm:"response_mapping" json:"responseMapping" description:"响应映射"`
|
||||
ResponseBodyMapping map[string]string `orm:"response_body_mapping" json:"responseBodyMapping" description:"响应主体映射"`
|
||||
ResponseBusinessFieldMapping map[string]string `orm:"response_business_field_mapping" json:"responseBusinessFieldMapping" description:"响应业务字段映射"`
|
||||
MaxConcurrency int `orm:"max_concurrency" json:"maxConcurrency" description:"最大并发数"`
|
||||
TokenMapping *TokenMapping `orm:"token_mapping" json:"tokenMapping" description:"token映射"`
|
||||
AsyncTaskMapping *AsyncTaskMapping `orm:"async_task_mapping" json:"asyncTaskMapping" description:"异步任务映射"`
|
||||
TokenPredictPrice float64 `orm:"token_predict_price" json:"tokenPredictPrice" description:"模型Token预估价格"`
|
||||
TokenPredictPriceUnit string `orm:"token_predict_price_unit" json:"tokenPredictPriceUnit" description:"模型token预估价格单位(秒,百万Token,千Token,字数)"`
|
||||
PriceConfig *PriceConfig `orm:"price_config" json:"priceConfig" description:"计费规则"`
|
||||
MaxTokens int `orm:"max_tokens" json:"maxTokens" description:"最大token数"`
|
||||
MinDuration int `orm:"min_duration" json:"minDuration" description:"最小时长(秒)"`
|
||||
MaxDuration int `orm:"max_duration" json:"maxDuration" description:"最大时长(秒)"`
|
||||
LastFrame string `orm:"last_frame" json:"lastFrame" description:"视频的尾帧图像"`
|
||||
}
|
||||
|
||||
type TokenMapping struct {
|
||||
PromptTokens string `json:"promptTokens" dc:"输入token"`
|
||||
CompletionTokens string `json:"completionTokens" dc:"输出token"`
|
||||
TotalTokens string `json:"totalTokens" dc:"总token"`
|
||||
}
|
||||
|
||||
type AsyncTaskMapping struct {
|
||||
Url string `json:"url" dc:"url"`
|
||||
HttpMethod string `json:"httpMethod" dc:"http方法" d:"POST"`
|
||||
RequestHeadMapping map[string]string `json:"requestHeadMapping" description:"请求头映射"`
|
||||
ResponseMapping map[string]any `json:"responseMapping" description:"响应映射"`
|
||||
TaskId string `json:"taskId" dc:"任务id"`
|
||||
TaskStatus string `json:"taskStatus" dc:"任务状态"`
|
||||
TaskStatusPending string `json:"taskStatusPending" dc:"任务状态-待处理"`
|
||||
TaskStatusRunning string `json:"taskStatusRunning" dc:"任务状态-运行中"`
|
||||
TaskStatusSuccess string `json:"taskStatusSuccess" dc:"任务状态-成功"`
|
||||
TaskStatusFailed string `json:"taskStatusFailed" dc:"任务状态-失败"`
|
||||
TaskStatusCancel string `json:"taskStatusCancel" dc:"任务状态-取消"`
|
||||
TaskStatusUnknown string `json:"taskStatusUnknown" dc:"任务状态-未知"`
|
||||
}
|
||||
|
||||
// PriceConfig 模型计费规则(price_config 列,JSONB)。
|
||||
// 命中条件为固定字段结构(PriceMatch):token 档位从调用用量读取,媒体类型由请求体参考媒体字段推导,
|
||||
// 全部字段缺省表示无条件命中。
|
||||
type PriceConfig struct {
|
||||
Currency string `json:"currency" dc:"币种,默认CNY"`
|
||||
Unit string `json:"unit" dc:"单价基准:per_1K-千token/per_1M-百万token/per_1-单个"`
|
||||
Rules []PriceRule `json:"rules" dc:"定价规则数组,按序首条命中生效"`
|
||||
Discount *PriceDiscount `json:"discount" dc:"模型级限时折扣,规则级可覆盖"`
|
||||
|
||||
// 单规则便捷字段:Rules 为空时的兜底价(等价于一条空 match 规则),全部为 0 时不参与计费
|
||||
InputPrice float64 `json:"inputPrice,omitempty" dc:"输入单价"`
|
||||
OutputPrice float64 `json:"outputPrice,omitempty" dc:"输出单价"`
|
||||
CacheHitPrice float64 `json:"cacheHitPrice,omitempty" dc:"缓存命中单价"`
|
||||
CacheStorageHourPrice float64 `json:"cacheStorageHourPrice,omitempty" dc:"缓存存储单价(元/小时)"`
|
||||
}
|
||||
|
||||
// PriceRule 定价规则:match 条件命中后按价格项计价,缺省项视为 0
|
||||
type PriceRule struct {
|
||||
Name string `json:"name"`
|
||||
Match *PriceMatch `json:"match,omitempty" dc:"命中条件(固定字段,见 PriceMatch);空表示任意调用"`
|
||||
Input float64 `json:"input" dc:"输入单价(非音频)"`
|
||||
InputAudio float64 `json:"inputAudio,omitempty" dc:"输入单价(音频),请求体 reference_audio 参考媒体字段命中时生效(见 DetectMediaType)"`
|
||||
Output float64 `json:"output" dc:"输出单价"`
|
||||
CacheHit float64 `json:"cacheHit" dc:"缓存命中单价(非音频)"`
|
||||
CacheHitAudio float64 `json:"cacheHitAudio,omitempty" dc:"缓存命中单价(音频),请求体 reference_audio 参考媒体字段命中时生效(见 DetectMediaType)"`
|
||||
CacheStorageHour float64 `json:"cacheStorageHour" dc:"缓存存储单价(元/小时)"`
|
||||
Discount *PriceDiscount `json:"discount" dc:"规则级折扣,覆盖模型级折扣"`
|
||||
}
|
||||
|
||||
// PriceMatch 命中条件:字段对应调用上下文固定路径,全部缺省(空值)表示无条件命中任意调用。
|
||||
// token 档位(InputLength/OutputLength/TotalLength/CachedTokens)从调用用量读取,
|
||||
// MediaType 由请求体参考媒体字段推导(见 DetectMediaType)。
|
||||
type PriceMatch struct {
|
||||
MediaType string `json:"mediaType,omitempty" dc:"输入媒体类型精确值(audio/no_video/has_video,由请求体参考媒体字段推导)"`
|
||||
InputLengthMax int64 `json:"inputLengthMax,omitempty" dc:"输入token上限(<=,usage.prompt_tokens)"`
|
||||
InputLengthMin int64 `json:"inputLengthMin,omitempty" dc:"输入token下限(>=,usage.prompt_tokens)"`
|
||||
OutputLengthMax int64 `json:"outputLengthMax,omitempty" dc:"输出token上限(<=,usage.completion_tokens)"`
|
||||
OutputLengthMin int64 `json:"outputLengthMin,omitempty" dc:"输出token下限(>=,usage.completion_tokens)"`
|
||||
TotalLengthMax int64 `json:"totalLengthMax,omitempty" dc:"总token上限(<=,usage.total_tokens)"`
|
||||
TotalLengthMin int64 `json:"totalLengthMin,omitempty" dc:"总token下限(>=,usage.total_tokens)"`
|
||||
CachedTokensMax int64 `json:"cachedTokensMax,omitempty" dc:"缓存命中token上限(<=,usage.cached_tokens)"`
|
||||
CachedTokensMin int64 `json:"cachedTokensMin,omitempty" dc:"缓存命中token下限(>=,usage.cached_tokens)"`
|
||||
}
|
||||
|
||||
// PriceDiscount 限时折扣:rate 为折扣率(0.4=4折),effective 为空数组表示长期有效
|
||||
type PriceDiscount struct {
|
||||
Rate float64 `json:"rate" dc:"折扣率"`
|
||||
Effective [2]string `json:"effective" dc:"有效期[起始,截止],格式YYYY-MM-DD,缺省长期有效"`
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type modelSessionCol struct {
|
||||
beans.SQLBaseCol
|
||||
ModelId string
|
||||
BizName string
|
||||
SessionId string
|
||||
RetryCount string
|
||||
RequestPath string
|
||||
ResponsePath string
|
||||
OriginalRequestPath string
|
||||
OriginalResponsePath string
|
||||
DurationSeconds string
|
||||
PromptTokens string
|
||||
CompletionTokens string
|
||||
TotalTokens string
|
||||
TotalCost string
|
||||
ErrorMsg string
|
||||
}
|
||||
|
||||
var ModelSessionCol = modelSessionCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
ModelId: "model_id",
|
||||
BizName: "biz_name",
|
||||
SessionId: "session_id",
|
||||
RetryCount: "retry_count",
|
||||
RequestPath: "request_path",
|
||||
ResponsePath: "response_path",
|
||||
OriginalRequestPath: "original_request_path",
|
||||
OriginalResponsePath: "original_response_path",
|
||||
DurationSeconds: "duration_seconds",
|
||||
PromptTokens: "prompt_tokens",
|
||||
CompletionTokens: "completion_tokens",
|
||||
TotalTokens: "total_tokens",
|
||||
TotalCost: "total_cost",
|
||||
ErrorMsg: "error_msg",
|
||||
}
|
||||
|
||||
// ModelSession 模型网关任务
|
||||
type ModelSession struct {
|
||||
beans.SQLBaseDO `orm:",inline"`
|
||||
ModelId int64 `orm:"model_id" json:"modelId" dc:"模型ID"`
|
||||
BizName string `orm:"biz_name" json:"bizName" dc:"业务名称"`
|
||||
SessionId string `orm:"session_id" json:"sessionId" dc:"会话ID"`
|
||||
RetryCount int `orm:"retry_count" json:"retryCount" dc:"重试"`
|
||||
RequestPath string `orm:"request_path" json:"requestPath" dc:"请求参数保存路径"`
|
||||
ResponsePath string `orm:"response_path" json:"responsePath" dc:"响应结果保存路径"`
|
||||
OriginalRequestPath string `orm:"original_request_path" json:"originalRequestPath" dc:"原始请求参数保存路径"`
|
||||
OriginalResponsePath string `orm:"original_response_path" json:"originalResponsePath" dc:"原始响应结果保存路径"`
|
||||
DurationSeconds int64 `orm:"duration_seconds" json:"durationSeconds" dc:"耗时(秒)"`
|
||||
PromptTokens int64 `orm:"prompt_tokens" json:"promptTokens" dc:"输入token"`
|
||||
CompletionTokens int64 `orm:"completion_tokens" json:"completionTokens" dc:"输出token"`
|
||||
TotalTokens int64 `orm:"total_tokens" json:"totalTokens" dc:"总token"`
|
||||
TotalCost float64 `orm:"total_cost" json:"totalCost" dc:"总费用(元)"`
|
||||
ErrorMsg string `orm:"error_msg" json:"errorMsg" dc:"错误消息"`
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type modelTaskEndCol struct {
|
||||
beans.SQLBaseCol
|
||||
ModelId string
|
||||
BizName string
|
||||
MsgTopic string
|
||||
RetryCount string
|
||||
ResponseParams string
|
||||
OriginalResponseParams string
|
||||
DurationSeconds string
|
||||
TaskId string
|
||||
PromptTokens string
|
||||
CompletionTokens string
|
||||
TotalTokens string
|
||||
TotalCost string
|
||||
ErrorMsg string
|
||||
}
|
||||
|
||||
var ModelTaskEndCol = modelTaskEndCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
ModelId: "model_id",
|
||||
BizName: "biz_name",
|
||||
MsgTopic: "msg_topic",
|
||||
RetryCount: "retry_count",
|
||||
ResponseParams: "response_params",
|
||||
OriginalResponseParams: "original_response_params",
|
||||
DurationSeconds: "duration_seconds",
|
||||
TaskId: "task_id",
|
||||
PromptTokens: "prompt_tokens",
|
||||
CompletionTokens: "completion_tokens",
|
||||
TotalTokens: "total_tokens",
|
||||
TotalCost: "total_cost",
|
||||
ErrorMsg: "error_msg",
|
||||
}
|
||||
|
||||
// ModelTaskEnd 模型网关任务
|
||||
type ModelTaskEnd struct {
|
||||
beans.SQLBaseDO `orm:",inline"`
|
||||
ModelId int64 `orm:"model_id" json:"modelId" dc:"模型ID"`
|
||||
BizName string `orm:"biz_name" json:"bizName" dc:"业务名称"`
|
||||
MsgTopic string `orm:"msg_topic" json:"msgTopic" dc:"消息主题"`
|
||||
RetryCount int `orm:"retry_count" json:"retryCount" dc:"重试"`
|
||||
ResponseParams string `orm:"response_params" json:"responseParams" dc:"响应结果"`
|
||||
OriginalResponseParams string `orm:"original_response_params" json:"originalResponseParams" dc:"原始响应结果"`
|
||||
DurationSeconds int64 `orm:"duration_seconds" json:"durationSeconds" dc:"耗时(秒)"`
|
||||
TaskId string `orm:"task_id" json:"taskId" dc:"任务ID"`
|
||||
PromptTokens int64 `orm:"prompt_tokens" json:"promptTokens" dc:"输入token"`
|
||||
CompletionTokens int64 `orm:"completion_tokens" json:"completionTokens" dc:"输出token"`
|
||||
TotalTokens int64 `orm:"total_tokens" json:"totalTokens" dc:"总token"`
|
||||
TotalCost float64 `orm:"total_cost" json:"totalCost" dc:"本次调用总费用(元),未配置计费规则为0"`
|
||||
ErrorMsg string `orm:"error_msg" json:"errorMsg" dc:"错误消息"`
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type modelTaskStartCol struct {
|
||||
beans.SQLBaseCol
|
||||
ModelId string
|
||||
BizName string
|
||||
MsgTopic string
|
||||
RetryCount string
|
||||
RequestPath string
|
||||
OriginalRequestPath string
|
||||
ResponseParams string
|
||||
OriginalResponseParams string
|
||||
DurationSeconds string
|
||||
TaskId string
|
||||
MediaType string
|
||||
ErrorMsg string
|
||||
}
|
||||
|
||||
var ModelTaskStartCol = modelTaskStartCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
ModelId: "model_id",
|
||||
BizName: "biz_name",
|
||||
MsgTopic: "msg_topic",
|
||||
RetryCount: "retry_count",
|
||||
RequestPath: "request_path",
|
||||
OriginalRequestPath: "original_request_path",
|
||||
ResponseParams: "response_params",
|
||||
OriginalResponseParams: "original_response_params",
|
||||
DurationSeconds: "duration_seconds",
|
||||
TaskId: "task_id",
|
||||
MediaType: "media_type",
|
||||
ErrorMsg: "error_msg",
|
||||
}
|
||||
|
||||
// ModelTaskStart 模型网关任务
|
||||
type ModelTaskStart struct {
|
||||
beans.SQLBaseDO `orm:",inline"`
|
||||
ModelId int64 `orm:"model_id" json:"modelId" dc:"模型ID"`
|
||||
BizName string `orm:"biz_name" json:"bizName" dc:"业务名称"`
|
||||
MsgTopic string `orm:"msg_topic" json:"msgTopic" dc:"消息主题"`
|
||||
RetryCount int `orm:"retry_count" json:"retryCount" dc:"重试"`
|
||||
RequestPath string `orm:"request_path" json:"requestPath" dc:"请求参数保存路径"`
|
||||
OriginalRequestPath string `orm:"original_request_path" json:"originalRequestPath" dc:"原始请求参数保存路径"`
|
||||
ResponseParams map[string]any `orm:"response_params" json:"responseParams" dc:"响应结果"`
|
||||
OriginalResponseParams map[string]any `orm:"original_response_params" json:"originalResponseParams" dc:"原始响应结果"`
|
||||
DurationSeconds int64 `orm:"duration_seconds" json:"durationSeconds" dc:"耗时(秒)"`
|
||||
TaskId string `orm:"task_id" json:"taskId" dc:"任务ID"`
|
||||
MediaType string `orm:"media_type" json:"mediaType" dc:"输入媒体类型快照(audio/no_video/has_video,创建任务时按请求体推导)"`
|
||||
ErrorMsg string `orm:"error_msg" json:"errorMsg" dc:"错误消息"`
|
||||
}
|
||||
Reference in New Issue
Block a user