Merge pull request #158 from APIParkLab/feature/ai-balance

Feature/ai balance
This commit is contained in:
Dot.L
2024-12-24 18:23:14 +08:00
committed by GitHub
21 changed files with 411 additions and 24 deletions
+7
View File
@@ -40,7 +40,14 @@ func (c *Config) Check(cfg string) error {
}
func (c *Config) GenConfig(target string, origin string) (string, error) {
if target == "" {
target = "{}"
}
if origin == "" {
origin = "{}"
}
var targetData map[string]interface{}
err := json.Unmarshal([]byte(target), &targetData)
if err != nil {
return "", err
+8
View File
@@ -20,10 +20,18 @@ type IProviderController interface {
Disable(ctx *gin.Context, id string) error
UpdateProviderConfig(ctx *gin.Context, id string, input *ai_dto.UpdateConfig) error
UpdateProviderDefaultLLM(ctx *gin.Context, id string, input *ai_dto.UpdateLLM) error
Sort(ctx *gin.Context, input *ai_dto.Sort) error
}
type IStatisticController interface {
APIs(ctx *gin.Context, keyword string, providerId string, start string, end string, page string, pageSize string, sortCondition string, asc string) ([]*ai_dto.APIItem, int64, error)
}
func init() {
autowire.Auto[IProviderController](func() reflect.Value {
return reflect.ValueOf(&imlProviderController{})
})
autowire.Auto[IStatisticController](func() reflect.Value {
return reflect.ValueOf(&imlStatisticController{})
})
}
+41
View File
@@ -1,6 +1,8 @@
package ai
import (
"strconv"
"github.com/APIParkLab/APIPark/module/ai"
ai_dto "github.com/APIParkLab/APIPark/module/ai/dto"
"github.com/eolinker/go-common/auto"
@@ -15,6 +17,10 @@ type imlProviderController struct {
module ai.IProviderModule `autowired:""`
}
func (i *imlProviderController) Sort(ctx *gin.Context, input *ai_dto.Sort) error {
return i.module.Sort(ctx, input)
}
func (i *imlProviderController) ConfiguredProviders(ctx *gin.Context) ([]*ai_dto.ConfiguredProviderItem, *auto.Label, error) {
return i.module.ConfiguredProviders(ctx)
}
@@ -50,3 +56,38 @@ func (i *imlProviderController) UpdateProviderConfig(ctx *gin.Context, id string
func (i *imlProviderController) UpdateProviderDefaultLLM(ctx *gin.Context, id string, input *ai_dto.UpdateLLM) error {
return i.module.UpdateProviderDefaultLLM(ctx, id, input)
}
var _ IStatisticController = (*imlStatisticController)(nil)
type imlStatisticController struct {
module ai.IAIAPIModule `autowired:""`
}
func (i *imlStatisticController) APIs(ctx *gin.Context, keyword string, providerId string, start string, end string, page string, pageSize string, sortCondition string, asc string) ([]*ai_dto.APIItem, int64, error) {
s, err := strconv.ParseInt(start, 10, 64)
if err != nil {
return nil, 0, err
}
e, err := strconv.ParseInt(end, 10, 64)
if err != nil {
return nil, 0, err
}
p, err := strconv.Atoi(page)
if err != nil {
if page != "" {
return nil, 0, err
}
p = 1
}
ps, err := strconv.Atoi(pageSize)
if err != nil {
if pageSize != "" {
return nil, 0, err
}
ps = 15
}
return i.module.APIs(ctx, keyword, providerId, s, e, p, ps, sortCondition, asc == "true")
}
+1 -1
View File
@@ -7,7 +7,7 @@ go 1.21
require (
github.com/eolinker/ap-account v1.0.15
github.com/eolinker/eosc v0.18.3
github.com/eolinker/go-common v1.1.1
github.com/eolinker/go-common v1.1.3
github.com/gabriel-vasile/mimetype v1.4.4
github.com/getkin/kin-openapi v0.127.0
github.com/gin-gonic/gin v1.10.0
+2 -2
View File
@@ -32,8 +32,8 @@ github.com/eolinker/ap-account v1.0.15 h1:n6DJeL6RHZ8eLlZUcY2U3H4d/GPaA5oelAx3R0
github.com/eolinker/ap-account v1.0.15/go.mod h1:zm/Ivs6waJ/M/nEszhpPmM6g50y/MKO+5eABFAdeD0g=
github.com/eolinker/eosc v0.18.3 h1:3IK5HkAPnJRfLbQ0FR7kWsZr6Y/OiqqGazvN1q2BL5A=
github.com/eolinker/eosc v0.18.3/go.mod h1:O9PQQXFCpB6fjHf+oFt/LN6EOAv779ItbMixMKCfTfk=
github.com/eolinker/go-common v1.1.1 h1:3WqqecGqcHDgpa8Ljp156c1uWeZKP1CKScdU+6sOfcc=
github.com/eolinker/go-common v1.1.1/go.mod h1:Kb/jENMN1mApnodvRgV4YwO9FJby1Jkt2EUjrBjvSX4=
github.com/eolinker/go-common v1.1.3 h1:Chb0x6sj0hZKpIN6Qo9IMdi9pX2KLNUPmqcaAD8mmWs=
github.com/eolinker/go-common v1.1.3/go.mod h1:Kb/jENMN1mApnodvRgV4YwO9FJby1Jkt2EUjrBjvSX4=
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY=
+13
View File
@@ -30,6 +30,19 @@ type APIItem struct {
Model ModelItem `json:"model"`
}
type AIAPIItem struct {
Id string `json:"id"`
Name string `json:"name"`
Service auto.Label `json:"service" aolabel:"service"`
Method string `json:"method"`
RequestPath string `json:"request_path"`
Model ModelItem `json:"model"`
Provider ProviderItem `json:"provider"`
UpdateTime auto.TimeLabel `json:"update_time"`
UseToken int64 `json:"use_token"`
Disable bool `json:"disable"`
}
type ModelItem struct {
Id string `json:"id"`
Logo string `json:"logo"`
+2
View File
@@ -112,6 +112,7 @@ func (i *imlAPIModule) Create(ctx context.Context, serviceId string, input *ai_a
Name: input.Name,
Service: serviceId,
Path: input.Path,
Disable: input.Disable,
Description: input.Description,
Timeout: input.Timeout,
Retry: input.Retry,
@@ -171,6 +172,7 @@ func (i *imlAPIModule) Edit(ctx context.Context, serviceId string, apiId string,
Model: modelId,
Provider: providerId,
AdditionalConfig: &apiInfo.AdditionalConfig,
Disable: input.Disable,
})
})
}
+2 -1
View File
@@ -2,9 +2,10 @@ package ai_api
import (
"context"
"reflect"
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
"github.com/eolinker/go-common/autowire"
"reflect"
)
type IAPIModule interface {
+4
View File
@@ -10,3 +10,7 @@ type UpdateConfig struct {
Priority *int `json:"priority"`
Enable *bool `json:"enable"`
}
type Sort struct {
Providers []string `json:"providers"`
}
+28 -5
View File
@@ -1,5 +1,9 @@
package ai_dto
import (
"github.com/eolinker/go-common/auto"
)
type Provider struct {
Id string `json:"id"`
Name string `json:"name"`
@@ -19,10 +23,16 @@ type ConfiguredProviderItem struct {
Status ProviderStatus `json:"status"`
APICount int64 `json:"api_count"`
KeyCount int `json:"key_count"`
KeyStatus []string `json:"key_status"`
KeyStatus []*KeyStatus `json:"key_status"`
Priority int `json:"priority"`
}
type KeyStatus struct {
Id string `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
}
type ProviderItem struct {
Id string `json:"id"`
Name string `json:"name"`
@@ -32,10 +42,11 @@ type ProviderItem struct {
}
type SimpleProviderItem struct {
Id string `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
Configured bool `json:"configured"`
Id string `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
Configured bool `json:"configured"`
Status ProviderStatus `json:"status"`
}
type LLMItem struct {
@@ -44,3 +55,15 @@ type LLMItem struct {
Config string `json:"config"`
Scopes []string `json:"scopes"`
}
type APIItem struct {
Id string `json:"id"`
Name string `json:"name"`
Service auto.Label `json:"service" aolabel:"service"`
Method string `json:"method"`
RequestPath string `json:"request_path"`
Model auto.Label `json:"model"`
UpdateTime auto.TimeLabel `json:"update_time"`
UseToken int `json:"use_token"`
Disable bool `json:"disable"`
}
+148 -10
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"sort"
"time"
@@ -59,6 +60,32 @@ type imlProviderModule struct {
transaction store.ITransaction `autowired:""`
}
func (i *imlProviderModule) Sort(ctx context.Context, input *ai_dto.Sort) error {
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
list, err := i.providerService.List(ctx)
if err != nil {
return err
}
providerMap := utils.SliceToMap(list, func(e *ai.Provider) string {
return e.Id
})
for index, id := range input.Providers {
_, has := providerMap[id]
if !has {
continue
}
priority := index + 1
err = i.providerService.Save(txCtx, id, &ai.SetProvider{
Priority: &priority,
})
if err != nil {
return err
}
}
return nil
})
}
func (i *imlProviderModule) ConfiguredProviders(ctx context.Context) ([]*ai_dto.ConfiguredProviderItem, *auto.Label, error) {
// 获取已配置的AI服务商
list, err := i.providerService.List(ctx)
@@ -71,6 +98,28 @@ func (i *imlProviderModule) ConfiguredProviders(ctx context.Context) ([]*ai_dto.
}
providers := make([]*ai_dto.ConfiguredProviderItem, 0, len(list))
for _, l := range list {
// 检查是否有默认Key
_, err = i.aiKeyService.DefaultKey(ctx, l.Id)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil, err
}
err = i.aiKeyService.Create(ctx, &ai_key.Create{
ID: l.Id,
Name: l.Name,
Config: l.Config,
Provider: l.Id,
Priority: 1,
Status: 1,
ExpireTime: 0,
UseToken: 0,
Default: true,
})
if err != nil {
return nil, nil, fmt.Errorf("create default key error:%v", err)
}
}
p, has := model_runtime.GetProvider(l.Id)
if !has {
continue
@@ -80,7 +129,7 @@ func (i *imlProviderModule) ConfiguredProviders(ctx context.Context) ([]*ai_dto.
return nil, nil, fmt.Errorf("get provider keys error:%v", err)
}
keysStatus := make([]string, 0, len(keys))
keysStatus := make([]*ai_dto.KeyStatus, 0, len(keys))
for _, k := range keys {
status := ai_key_dto.ToKeyStatus(k.Status)
switch status {
@@ -88,11 +137,13 @@ func (i *imlProviderModule) ConfiguredProviders(ctx context.Context) ([]*ai_dto.
default:
status = ai_key_dto.KeyError
}
keysStatus = append(keysStatus, status.String())
}
if len(keysStatus) == 0 {
keysStatus = []string{ai_key_dto.KeyNormal.String()}
keysStatus = append(keysStatus, &ai_dto.KeyStatus{
Id: k.ID,
Name: k.Name,
Status: status.String(),
})
}
providers = append(providers, &ai_dto.ConfiguredProviderItem{
Id: l.Id,
Name: l.Name,
@@ -143,12 +194,14 @@ func (i *imlProviderModule) SimpleProviders(ctx context.Context) ([]*ai_dto.Simp
items := make([]*ai_dto.SimpleProviderItem, 0, len(providers))
for _, v := range providers {
item := &ai_dto.SimpleProviderItem{
Id: v.ID(),
Name: v.Name(),
Logo: v.Logo(),
Id: v.ID(),
Name: v.Name(),
Logo: v.Logo(),
Status: ai_dto.ProviderDisabled,
}
if _, has := providerMap[v.ID()]; has {
if info, has := providerMap[v.ID()]; has {
item.Configured = true
item.Status = ai_dto.ToProviderStatus(info.Status)
}
items = append(items, item)
}
@@ -403,7 +456,7 @@ func (i *imlProviderModule) UpdateProviderConfig(ctx context.Context, id string,
}
pInfo := &ai.SetProvider{
Name: &info.Name,
DefaultLLM: &info.DefaultLLM,
DefaultLLM: &input.DefaultLLM,
Config: &input.Config,
Priority: input.Priority,
}
@@ -568,3 +621,88 @@ func (i *imlProviderModule) syncGateway(ctx context.Context, clusterId string, r
return nil
}
var _ IAIAPIModule = (*imlAIApiModule)(nil)
type imlAIApiModule struct {
aiAPIService ai_api.IAPIService `autowired:""`
aiAPIUseService ai_api.IAPIUseService `autowired:""`
}
func (i *imlAIApiModule) APIs(ctx context.Context, keyword string, providerId string, start int64, end int64, page int, pageSize int, sortCondition string, asc bool) ([]*ai_dto.APIItem, int64, error) {
sortRule := "desc"
if asc {
sortRule = "asc"
}
switch sortCondition {
default:
apis, err := i.aiAPIService.Search(ctx, keyword, map[string]interface{}{
"provider": providerId,
}, "update_at desc")
if err != nil {
return nil, 0, err
}
if len(apis) <= 0 {
return nil, 0, nil
}
apiMap := make(map[string]*ai_api.API)
apiIds := make([]string, 0, len(apis))
for _, a := range apis {
apiMap[a.ID] = a
apiIds = append(apiIds, a.ID)
}
offset := (page - 1) * pageSize
results, _, err := i.aiAPIUseService.SumByApisPage(ctx, providerId, start, end, offset, pageSize, fmt.Sprintf("total_token %s", sortRule), apiIds...)
if err != nil {
return nil, 0, err
}
apiItems := utils.SliceToSlice(results, func(e *ai_api.APIUse) *ai_dto.APIItem {
info := apiMap[e.API]
delete(apiMap, e.API)
return &ai_dto.APIItem{
Id: e.API,
Name: info.Name,
Service: auto.UUID(info.Service),
Method: http.MethodPost,
RequestPath: info.Path,
Model: auto.Label{
Id: info.Model,
Name: info.Model,
},
UpdateTime: auto.TimeLabel(info.UpdateAt),
UseToken: e.TotalToken,
Disable: info.Disable,
}
})
sortApis := make([]*ai_dto.APIItem, 0, len(apiMap))
for _, a := range apiMap {
sortApis = append(sortApis, &ai_dto.APIItem{
Id: a.ID,
Name: a.Name,
Service: auto.UUID(a.Service),
Method: http.MethodPost,
RequestPath: a.Path,
Model: auto.Label{
Id: a.Model,
Name: a.Model,
},
UpdateTime: auto.TimeLabel(a.UpdateAt),
UseToken: 0,
Disable: a.Disable,
})
}
// 排序
sort.Slice(sortApis, func(i, j int) bool {
return time.Time(sortApis[i].UpdateTime).After(time.Time(sortApis[j].UpdateTime))
})
size := pageSize - len(apiItems)
for i := offset; i < offset+size && i < len(sortApis); i++ {
apiItems = append(apiItems, sortApis[i])
}
total := int64(len(apis))
return apiItems, total, nil
}
}
+9
View File
@@ -20,6 +20,11 @@ type IProviderModule interface {
UpdateProviderStatus(ctx context.Context, id string, enable bool) error
UpdateProviderConfig(ctx context.Context, id string, input *ai_dto.UpdateConfig) error
UpdateProviderDefaultLLM(ctx context.Context, id string, input *ai_dto.UpdateLLM) error
Sort(ctx context.Context, input *ai_dto.Sort) error
}
type IAIAPIModule interface {
APIs(ctx context.Context, keyword string, providerId string, start int64, end int64, page int, pageSize int, sortCondition string, asc bool) ([]*ai_dto.APIItem, int64, error)
}
func init() {
@@ -28,4 +33,8 @@ func init() {
gateway.RegisterInitHandleFunc(module.initGateway)
return reflect.ValueOf(module)
})
autowire.Auto[IAIAPIModule](func() reflect.Value {
return reflect.ValueOf(new(imlAIApiModule))
})
}
+4 -4
View File
@@ -12,13 +12,13 @@ func (p *plugin) aiAPIs() []pm3.Api {
return []pm3.Api{
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/providers/unconfigured", []string{"context"}, []string{"providers"}, p.aiProviderController.UnConfiguredProviders, access.SystemSettingsAiProviderView),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/providers/configured", []string{"context"}, []string{"providers", "backup"}, p.aiProviderController.ConfiguredProviders, access.SystemSettingsAiProviderView),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers/configured", []string{"context"}, []string{"providers"}, p.aiProviderController.SimpleProviders),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers", []string{"context"}, []string{"providers"}, p.aiProviderController.SimpleProviders),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/config", []string{"context", "query:provider"}, []string{"provider"}, p.aiProviderController.Provider, access.SystemSettingsAiProviderView),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/llms", []string{"context", "query:provider"}, []string{"llms", "provider"}, p.aiProviderController.LLMs),
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/enable", []string{"context", "query:provider"}, nil, p.aiProviderController.isStop),
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/disable", []string{"context", "query:provider"}, nil, p.aiProviderController.Disable),
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/sort", []string{"context", "body"}, nil, p.aiProviderController.Sort),
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/config", []string{"context", "query:provider", "body"}, nil, p.aiProviderController.UpdateProviderConfig, access.SystemSettingsAiProviderManager),
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/default-llm", []string{"context", "query:provider", "body"}, nil, p.aiProviderController.UpdateProviderDefaultLLM),
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/apis", []string{"context", "query:keyword", "query:provider", "query:start", "query:end", "query:page", "query:page_size", "query:sort", "query:asc"}, []string{"apis", "total"}, p.aiStatisticController.APIs),
}
}
+1
View File
@@ -76,6 +76,7 @@ type plugin struct {
upstreamController upstream.IUpstreamController `autowired:""`
routerController router.IRouterController `autowired:""`
aiAPIController ai_api.IAPIController `autowired:""`
aiStatisticController ai.IStatisticController `autowired:""`
aiKeyController ai_key.IKeyController `autowired:""`
apiDocController router.IAPIDocController `autowired:""`
subscribeController subscribe.ISubscribeController `autowired:""`
+30
View File
@@ -100,6 +100,36 @@ system:
value: 'manager'
dependents:
- system.settings.ai_provider.view
- name: ai key resource
value: 'ai_key_resource'
children:
- name: view
value: 'view'
guest_allow: true
- name: manager
value: 'manager'
dependents:
- system.settings.ai_key_resource.view
- name: ai api
value: 'ai_api'
children:
- name: view
value: 'view'
guest_allow: true
- name: manager
value: 'manager'
dependents:
- system.settings.ai_api.view
- name: ai log
value: 'ai_log'
children:
- name: view
value: 'view'
guest_allow: true
- name: manager
value: 'manager'
dependents:
- system.settings.ai_log.view
- name: ssl certificate
cname: 证书
value: 'ssl_certificate'
+12
View File
@@ -6,6 +6,12 @@ system:
- system.api_portal.api_portal.view
- system.settings.account.manager
- system.settings.account.view
- system.settings.ai_api.manager
- system.settings.ai_api.view
- system.settings.ai_key_resource.manager
- system.settings.ai_key_resource.view
- system.settings.ai_log.manager
- system.settings.ai_log.view
- system.settings.ai_provider.manager
- system.settings.ai_provider.view
- system.settings.api_gateway.manager
@@ -39,6 +45,12 @@ system:
permits:
- system.analysis.run_view.view
- system.api_portal.api_portal.view
- system.settings.ai_api.manager
- system.settings.ai_api.view
- system.settings.ai_key_resource.manager
- system.settings.ai_key_resource.view
- system.settings.ai_log.manager
- system.settings.ai_log.view
- system.settings.ai_provider.manager
- system.settings.ai_provider.view
- system.settings.api_gateway.manager
+47
View File
@@ -5,6 +5,8 @@ import (
"encoding/json"
"time"
"github.com/eolinker/go-common/utils"
"github.com/APIParkLab/APIPark/service/universally"
"github.com/APIParkLab/APIPark/stores/api"
)
@@ -50,6 +52,7 @@ func createEntityHandler(i *Create) *api.AiAPIInfo {
Retry: i.Retry,
Model: i.Model,
Provider: i.Provider,
Disable: i.Disable,
CreateAt: now,
UpdateAt: now,
AdditionalConfig: string(cfg),
@@ -81,5 +84,49 @@ func updateHandler(e *api.AiAPIInfo, i *Edit) {
cfg, _ := json.Marshal(i.AdditionalConfig)
e.AdditionalConfig = string(cfg)
}
if i.Disable != nil {
e.Disable = *i.Disable
}
e.UpdateAt = time.Now()
}
var _ IAPIUseService = (*imlAPIUseService)(nil)
type imlAPIUseService struct {
store api.IAiAPIUseStore `autowired:""`
}
func (i *imlAPIUseService) SumByApisPage(ctx context.Context, providerId string, start, end int64, offset, limit int, order string, apiIds ...string) ([]*APIUse, int64, error) {
list, total, err := i.store.SumByGroupPage(ctx, "api", order, offset, limit, "api,sum(input_token) as input_token,sum(output_token) as output_token,sum(total_token) as total_token", "provider = ? and api in (?) and minute >= ? and minute <= ?", providerId, apiIds, start, end)
if err != nil {
return nil, 0, err
}
result := make([]*APIUse, 0, len(list))
for _, v := range list {
result = append(result, &APIUse{
API: v.API,
InputToken: v.InputToken,
OutputToken: v.OutputToken,
TotalToken: v.TotalToken,
})
}
return result, total, nil
}
func (i *imlAPIUseService) SumByApis(ctx context.Context, providerId string, start, end int64, apiIds ...string) ([]*APIUse, error) {
list, err := i.store.SumByGroup(ctx, "api", "api,sum(input_token) as input_token,sum(output_token) as output_token,sum(total_token) as total_token", "provider = ? and api in (?) and minute >= ? and minute <= ?", providerId, apiIds, start, end)
if err != nil {
return nil, err
}
return utils.SliceToSlice(list, func(v *api.AiAPIUse) *APIUse {
return &APIUse{
API: v.API,
InputToken: v.InputToken,
OutputToken: v.OutputToken,
TotalToken: v.TotalToken,
}
}), nil
}
+10
View File
@@ -36,6 +36,7 @@ type Create struct {
Model string
Provider string
AdditionalConfig map[string]interface{}
Disable bool
}
type Edit struct {
@@ -46,6 +47,7 @@ type Edit struct {
Retry *int
Provider *string
Model *string
Disable *bool
AdditionalConfig *map[string]interface{}
}
@@ -67,6 +69,14 @@ func FromEntity(e *api.AiAPIInfo) *API {
UpdateAt: e.UpdateAt,
Creator: e.Creator,
Updater: e.Updater,
Disable: e.Disable,
AdditionalConfig: cfg,
}
}
type APIUse struct {
API string
InputToken int
OutputToken int
TotalToken int
}
+7 -1
View File
@@ -14,12 +14,18 @@ type IAPIService interface {
universally.IServiceEdit[Edit]
universally.IServiceDelete
CountMapByProvider(ctx context.Context, keyword string, conditions map[string]interface{}) (map[string]int64, error)
}
//ListByServices(ctx context.Context, serviceIds ...string) ([]*API, error)
type IAPIUseService interface {
SumByApis(ctx context.Context, providerId string, start, end int64, apiIds ...string) ([]*APIUse, error)
SumByApisPage(ctx context.Context, providerId string, start, end int64, page, pageSize int, order string, apiIds ...string) ([]*APIUse, int64, error)
}
func init() {
autowire.Auto[IAPIService](func() reflect.Value {
return reflect.ValueOf(new(imlAPIService))
})
autowire.Auto[IAPIUseService](func() reflect.Value {
return reflect.ValueOf(new(imlAPIUseService))
})
}
+12
View File
@@ -31,6 +31,14 @@ type imlAiAPIInfoStore struct {
store.SearchStoreSoftDelete[AiAPIInfo]
}
type IAiAPIUseStore interface {
store.IStatisticsStore[AiAPIUse]
}
type imlAiAPIUseStore struct {
store.StatisticsStore[AiAPIUse]
}
func init() {
autowire.Auto[IApiBaseStore](func() reflect.Value {
@@ -48,4 +56,8 @@ func init() {
autowire.Auto[IAiAPIInfoStore](func() reflect.Value {
return reflect.ValueOf(new(imlAiAPIInfoStore))
})
autowire.Auto[IAiAPIUseStore](func() reflect.Value {
return reflect.ValueOf(new(imlAiAPIUseStore))
})
}
+23
View File
@@ -85,6 +85,8 @@ type AiAPIInfo struct {
Updater string `gorm:"size:36;not null;column:updater;comment:更新人;index:updater" aovalue:"updater"`
UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:update_at;comment:更新时间"`
AdditionalConfig string `gorm:"type:text;null;column:additional_config;comment:额外配置"`
UseToken int `gorm:"type:int(11);not null;column:use_token;comment:使用token"`
Disable bool `gorm:"type:tinyint(1);not null;column:disable;comment:是否禁用 0:否 1:是"`
IsDelete bool `gorm:"type:tinyint(1);not null;column:is_delete;comment:是否删除 0:否 1:是"`
}
@@ -95,3 +97,24 @@ func (a *AiAPIInfo) TableName() string {
func (a *AiAPIInfo) IdValue() int64 {
return a.Id
}
type AiAPIUse struct {
Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"`
API string `gorm:"size:36;not null;column:api;comment:API;index:api"`
Service string `gorm:"size:36;not null;column:service;comment:服务;index:service"`
Provider string `gorm:"size:36;not null;column:provider;comment:提供者;index:provider"`
Day int `gorm:"type:int(11);not null;column:day;comment:当前日期"`
Hour int `gorm:"type:int(11);not null;column:hour;comment:当前小时"`
Minute int `gorm:"type:int(11);not null;column:minute;comment:当前分钟"`
InputToken int `gorm:"type:int(11);not null;column:input_token;comment:输入token"`
OutputToken int `gorm:"type:int(11);not null;column:output_token;comment:输出token"`
TotalToken int `gorm:"type:int(11);not null;column:total_token;comment:总token"`
}
func (a *AiAPIUse) TableName() string {
return "ai_api_use"
}
func (a *AiAPIUse) IdValue() int64 {
return a.Id
}