mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
ai路由完成
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package ai_api_dto
|
||||
|
||||
type CreateAPI struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
AiPrompt *AiPrompt `json:"ai_prompt"`
|
||||
AiModel *AiModel `json:"ai_model"`
|
||||
Timeout int `json:"timeout"`
|
||||
Retry int `json:"retry"`
|
||||
}
|
||||
|
||||
type AiPrompt struct {
|
||||
Variables []*AiPromptVariable `json:"variables"`
|
||||
Prompt string `json:"prompt"`
|
||||
}
|
||||
|
||||
type AiPromptVariable struct {
|
||||
Key string `json:"key"`
|
||||
Description string `json:"description"`
|
||||
Require bool `json:"require"`
|
||||
}
|
||||
|
||||
type AiModel struct {
|
||||
Id string `json:"id"`
|
||||
Config string `json:"config"`
|
||||
}
|
||||
|
||||
type EditAPI struct {
|
||||
Name *string `json:"name"`
|
||||
Path *string `json:"path"`
|
||||
Description *string `json:"description"`
|
||||
Disable *bool `json:"disable"`
|
||||
AiPrompt *AiPrompt `json:"ai_prompt"`
|
||||
AiModel *AiModel `json:"ai_model"`
|
||||
Timeout *int `json:"timeout"`
|
||||
Retry *int `json:"retry"`
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ai_api_dto
|
||||
|
||||
import (
|
||||
"github.com/eolinker/go-common/auto"
|
||||
)
|
||||
|
||||
type API struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
AiPrompt *AiPrompt `json:"ai_prompt"`
|
||||
AiModel *AiModel `json:"ai_model"`
|
||||
Timeout int `json:"timeout"`
|
||||
Retry int `json:"retry"`
|
||||
}
|
||||
|
||||
type APIItem struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RequestPath string `json:"request_path"`
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
Creator auto.Label `json:"creator" aolabel:"user"`
|
||||
Updater auto.Label `json:"updater" aolabel:"user"`
|
||||
CreateTime auto.TimeLabel `json:"create_time"`
|
||||
UpdateTime auto.TimeLabel `json:"update_time"`
|
||||
Model ModelItem `json:"model"`
|
||||
}
|
||||
|
||||
type ModelItem struct {
|
||||
Id string `json:"id"`
|
||||
Logo string `json:"logo"`
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package ai_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
|
||||
"github.com/APIParkLab/APIPark/module/ai/provider"
|
||||
ai_api "github.com/APIParkLab/APIPark/service/ai-api"
|
||||
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
"github.com/eolinker/go-common/auto"
|
||||
"github.com/eolinker/go-common/store"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var _ IAPIModule = (*imlAPIModule)(nil)
|
||||
|
||||
var (
|
||||
openapi3Loader = openapi3.NewLoader()
|
||||
)
|
||||
|
||||
type imlAPIModule struct {
|
||||
serviceService service.IServiceService `autowired:""`
|
||||
apiDocService api_doc.IAPIDocService `autowired:""`
|
||||
aiAPIService ai_api.IAPIService `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) getAPIDoc(ctx context.Context, serviceId string) (*openapi3.T, error) {
|
||||
doc, err := i.apiDocService.GetDoc(ctx, serviceId)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get service info error:%v", err)
|
||||
}
|
||||
return genOpenAPI3Template(info.Name, info.Description), nil
|
||||
}
|
||||
return openapi3Loader.LoadFromData([]byte(doc.Content))
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) updateAPIDoc(ctx context.Context, serviceId string, path string, description string, aiPrompt *ai_api_dto.AiPrompt) error {
|
||||
doc, err := i.getAPIDoc(ctx, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var variables []*ai_api_dto.AiPromptVariable
|
||||
if aiPrompt != nil {
|
||||
variables = aiPrompt.Variables
|
||||
}
|
||||
doc.AddOperation(path, http.MethodPost, genOperation(description, variables))
|
||||
result, err := doc.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.apiDocService.UpdateDoc(ctx, serviceId, &api_doc.UpdateDoc{
|
||||
ID: uuid.New().String(),
|
||||
Content: string(result),
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) deleteAPIDoc(ctx context.Context, serviceId string, path string) error {
|
||||
doc, err := i.getAPIDoc(ctx, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc.Paths.Delete(path)
|
||||
result, err := doc.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.apiDocService.UpdateDoc(ctx, serviceId, &api_doc.UpdateDoc{
|
||||
ID: uuid.New().String(),
|
||||
Content: string(result),
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) Create(ctx context.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error) {
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Kind != service.AIService {
|
||||
return nil, fmt.Errorf("service kind is not ai service")
|
||||
}
|
||||
if input.Id == "" {
|
||||
input.Id = uuid.New().String()
|
||||
}
|
||||
err = i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
err := i.updateAPIDoc(ctx, serviceId, input.Path, input.Description, input.AiPrompt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.aiAPIService.Create(ctx, &ai_api.Create{
|
||||
ID: input.Id,
|
||||
Name: input.Name,
|
||||
Service: serviceId,
|
||||
Path: input.Path,
|
||||
Description: input.Description,
|
||||
Timeout: input.Timeout,
|
||||
Retry: input.Retry,
|
||||
Model: input.AiModel.Id,
|
||||
AdditionalConfig: map[string]interface{}{
|
||||
"ai_prompt": input.AiPrompt,
|
||||
"ai_model": input.AiModel,
|
||||
},
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return i.Get(ctx, serviceId, input.Id)
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) Edit(ctx context.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error) {
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Kind != service.AIService {
|
||||
return nil, fmt.Errorf("service kind is not ai service")
|
||||
}
|
||||
|
||||
err = i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
apiInfo, err := i.aiAPIService.Get(ctx, apiId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if input.Path != nil {
|
||||
apiInfo.Path = *input.Path
|
||||
}
|
||||
if input.Description != nil {
|
||||
apiInfo.Description = *input.Description
|
||||
}
|
||||
err = i.updateAPIDoc(ctx, serviceId, apiInfo.Path, apiInfo.Description, input.AiPrompt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var modelId *string
|
||||
if input.AiModel != nil {
|
||||
modelId = &input.AiModel.Id
|
||||
}
|
||||
if input.AiPrompt != nil {
|
||||
apiInfo.AdditionalConfig["ai_prompt"] = input.AiPrompt
|
||||
}
|
||||
if input.AiModel != nil {
|
||||
apiInfo.AdditionalConfig["ai_model"] = input.AiModel
|
||||
}
|
||||
return i.aiAPIService.Save(ctx, apiId, &ai_api.Edit{
|
||||
Name: input.Name,
|
||||
Path: input.Path,
|
||||
Description: input.Description,
|
||||
Timeout: input.Timeout,
|
||||
Retry: input.Retry,
|
||||
Model: modelId,
|
||||
AdditionalConfig: &apiInfo.AdditionalConfig,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return i.Get(ctx, serviceId, apiId)
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) Delete(ctx context.Context, serviceId string, apiId string) error {
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Kind != service.AIService {
|
||||
return fmt.Errorf("service kind is not ai service")
|
||||
}
|
||||
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
err = i.deleteAPIDoc(ctx, serviceId, apiId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.aiAPIService.Delete(ctx, apiId)
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) List(ctx context.Context, keyword string, serviceId string) ([]*ai_api_dto.APIItem, error) {
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Kind != service.AIService {
|
||||
return nil, fmt.Errorf("service kind is not ai service")
|
||||
}
|
||||
apis, err := i.aiAPIService.Search(ctx, keyword, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
}, "update_at desc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, has := provider.GetProvider(info.AdditionalConfig["provider"])
|
||||
if !has {
|
||||
return nil, fmt.Errorf("provider not found")
|
||||
}
|
||||
return utils.SliceToSlice(apis, func(t *ai_api.API) *ai_api_dto.APIItem {
|
||||
modelItem := ai_api_dto.ModelItem{
|
||||
Id: t.Model,
|
||||
}
|
||||
model, has := p.LLM(t.Model)
|
||||
if has {
|
||||
modelItem.Logo = model.Logo
|
||||
}
|
||||
return &ai_api_dto.APIItem{
|
||||
Id: t.ID,
|
||||
Name: t.Name,
|
||||
RequestPath: t.Path,
|
||||
Description: t.Description,
|
||||
Disable: t.Disable,
|
||||
Creator: auto.UUID(t.Creator),
|
||||
Updater: auto.UUID(t.Updater),
|
||||
CreateTime: auto.TimeLabel(t.CreateAt),
|
||||
UpdateTime: auto.TimeLabel(t.UpdateAt),
|
||||
Model: modelItem,
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIModule) Get(ctx context.Context, serviceId string, apiId string) (*ai_api_dto.API, error) {
|
||||
info, err := i.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Kind != service.AIService {
|
||||
return nil, fmt.Errorf("service kind is not ai service")
|
||||
}
|
||||
apiInfo, err := i.aiAPIService.Get(ctx, apiId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prompt, err := ConvertStruct[ai_api_dto.AiPrompt](apiInfo.AdditionalConfig["ai_prompt"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aiModel, err := ConvertStruct[ai_api_dto.AiModel](apiInfo.AdditionalConfig["ai_model"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ai_api_dto.API{
|
||||
Id: apiInfo.ID,
|
||||
Name: apiInfo.Name,
|
||||
Path: apiInfo.Path,
|
||||
Description: apiInfo.Description,
|
||||
Disable: apiInfo.Disable,
|
||||
AiPrompt: prompt,
|
||||
AiModel: aiModel,
|
||||
Timeout: apiInfo.Timeout,
|
||||
Retry: apiInfo.Retry,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ConvertStruct[T any](data interface{}) (*T, error) {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var t T
|
||||
err = json.Unmarshal(b, &t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ai_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type IAPIModule interface {
|
||||
Create(ctx context.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error)
|
||||
Edit(ctx context.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error)
|
||||
Delete(ctx context.Context, serviceId string, apiId string) error
|
||||
List(ctx context.Context, keyword, serviceId string) ([]*ai_api_dto.APIItem, error)
|
||||
Get(ctx context.Context, serviceId string, apiId string) (*ai_api_dto.API, error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IAPIModule](func() reflect.Value {
|
||||
m := new(imlAPIModule)
|
||||
return reflect.ValueOf(m)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package ai_api
|
||||
|
||||
import (
|
||||
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
func genOpenAPI3Template(title string, description string) *openapi3.T {
|
||||
result := new(openapi3.T)
|
||||
result.OpenAPI = "3.1.0"
|
||||
result.Info = &openapi3.Info{
|
||||
Title: title,
|
||||
Description: description,
|
||||
Version: "beta",
|
||||
}
|
||||
result.Components = genComponents()
|
||||
result.Paths = new(openapi3.Paths)
|
||||
return result
|
||||
}
|
||||
|
||||
func genOperation(description string, variables []*ai_api_dto.AiPromptVariable) *openapi3.Operation {
|
||||
operation := openapi3.NewOperation()
|
||||
operation.RequestBody = genRequestBody(variables)
|
||||
operation.Responses = &openapi3.Responses{}
|
||||
operation.Responses.Set("200", genResponse())
|
||||
operation.Description = description
|
||||
return operation
|
||||
}
|
||||
|
||||
func genRequestBody(variables []*ai_api_dto.AiPromptVariable) *openapi3.RequestBodyRef {
|
||||
requestBody := openapi3.NewRequestBody()
|
||||
requestBody.Content = openapi3.NewContentWithSchema(genRequestBodySchema(variables), []string{"application/json"})
|
||||
return &openapi3.RequestBodyRef{
|
||||
Value: requestBody,
|
||||
}
|
||||
}
|
||||
|
||||
func genResponse() *openapi3.ResponseRef {
|
||||
response := openapi3.NewResponse()
|
||||
response.Content = openapi3.NewContentWithSchema(genResponseSchema(), []string{"application/json"})
|
||||
description := "Response from the server"
|
||||
response.Description = &description
|
||||
return &openapi3.ResponseRef{
|
||||
Value: response,
|
||||
}
|
||||
}
|
||||
|
||||
func genRequestBodySchema(variables []*ai_api_dto.AiPromptVariable) *openapi3.Schema {
|
||||
result := openapi3.NewObjectSchema()
|
||||
variableSchema := openapi3.NewObjectSchema()
|
||||
required := make([]string, 0, len(variables))
|
||||
for _, v := range variables {
|
||||
val := openapi3.NewStringSchema()
|
||||
val.Description = v.Description
|
||||
if v.Require {
|
||||
required = append(required, v.Key)
|
||||
}
|
||||
variableSchema.WithProperty(v.Key, val)
|
||||
}
|
||||
result.WithProperty("variables", variableSchema.WithRequired(required))
|
||||
result.WithProperty("messages", genMessageSchema())
|
||||
result.WithRequired([]string{"variables", "messages"})
|
||||
return result
|
||||
}
|
||||
|
||||
func genComponents() *openapi3.Components {
|
||||
components := openapi3.NewComponents()
|
||||
components.Schemas = make(openapi3.Schemas)
|
||||
components.Schemas["Message"] = genMessageSchema().NewRef()
|
||||
components.Schemas["Response"] = genResponseSchema().NewRef()
|
||||
return &components
|
||||
}
|
||||
|
||||
func genMessageSchema() *openapi3.Schema {
|
||||
messageSchema := openapi3.NewObjectSchema()
|
||||
messageSchema.Title = "Message"
|
||||
messageSchema.Description = "Chat Message"
|
||||
roleSchema := openapi3.NewStringSchema()
|
||||
roleSchema.Description = "Role of the message sender"
|
||||
roleSchema.Example = "assistant"
|
||||
contentSchema := openapi3.NewStringSchema()
|
||||
contentSchema.Description = "The message content"
|
||||
contentSchema.Example = "Hello, how can I help you?"
|
||||
messageSchema.WithProperties(map[string]*openapi3.Schema{
|
||||
"role": roleSchema,
|
||||
"content": contentSchema,
|
||||
})
|
||||
return messageSchema
|
||||
}
|
||||
|
||||
func genResponseSchema() *openapi3.Schema {
|
||||
responseSchema := openapi3.NewObjectSchema()
|
||||
responseSchema.Description = "Response from the server"
|
||||
responseSchema.WithPropertyRef("message", openapi3.NewSchemaRef("#/components/schemas/Message", genMessageSchema()))
|
||||
responseSchema.WithProperty("code", openapi3.NewInt32Schema().WithMin(0))
|
||||
responseSchema.WithProperty("error", openapi3.NewStringSchema())
|
||||
responseSchema.WithProperty("finish_reason", openapi3.NewStringSchema().WithEnum([]string{
|
||||
"stop",
|
||||
"length",
|
||||
"function_call",
|
||||
"content_filter",
|
||||
"null",
|
||||
}))
|
||||
return responseSchema
|
||||
}
|
||||
@@ -8,11 +8,12 @@ type Provider struct {
|
||||
}
|
||||
|
||||
type ProviderItem struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DefaultLLM string `json:"default_llm"`
|
||||
Logo string `json:"logo"`
|
||||
Configured bool `json:"configured"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
DefaultLLM string `json:"default_llm"`
|
||||
DefaultLLMLogo string `json:"default_llm_logo"`
|
||||
Logo string `json:"logo"`
|
||||
Configured bool `json:"configured"`
|
||||
}
|
||||
|
||||
type SimpleProviderItem struct {
|
||||
|
||||
@@ -69,11 +69,16 @@ func (i *imlProviderModule) Providers(ctx context.Context) ([]*ai_dto.ProviderIt
|
||||
DefaultLLM: v.Info().DefaultLLM,
|
||||
}
|
||||
if info, has := providerMap[v.Info().Id]; has {
|
||||
llm, has := v.LLM(info.DefaultLLM)
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
err = v.GlobalConfig().CheckConfig(info.Config)
|
||||
if err == nil {
|
||||
item.Configured = true
|
||||
}
|
||||
item.DefaultLLM = info.DefaultLLM
|
||||
item.DefaultLLMLogo = llm.Logo
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"github.com/APIParkLab/APIPark/module/ai/provider"
|
||||
"github.com/eolinker/eosc"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -27,19 +28,23 @@ type ModelData struct {
|
||||
type Model struct {
|
||||
globalConfig provider.IAIConfig
|
||||
invokeConfig provider.IAIConfig
|
||||
models []*ModelData
|
||||
models eosc.Untyped[string, *ModelData]
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func NewModel() provider.IAIProvider {
|
||||
modelData := make([]*ModelData, 0)
|
||||
json.Unmarshal(modelJson, &modelData)
|
||||
return &Model{
|
||||
m := &Model{
|
||||
globalConfig: NewGlobalConfigDriver(),
|
||||
invokeConfig: NewInvokeConfigDriver(),
|
||||
models: modelData,
|
||||
models: eosc.BuildUntyped[string, *ModelData](),
|
||||
locker: sync.RWMutex{},
|
||||
}
|
||||
for _, v := range modelData {
|
||||
m.models.Set(v.Id, v)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Model) Index() int {
|
||||
@@ -83,11 +88,9 @@ func (m *Model) UpdateLLMs() error {
|
||||
}
|
||||
|
||||
func (m *Model) LLMs() []*provider.LLM {
|
||||
m.locker.RLock()
|
||||
models := m.models
|
||||
m.locker.RUnlock()
|
||||
result := make([]*provider.LLM, 0, len(models))
|
||||
for _, model := range models {
|
||||
result := make([]*provider.LLM, 0, models.Count())
|
||||
for _, model := range models.List() {
|
||||
llm := &provider.LLM{
|
||||
Id: model.Id,
|
||||
Logo: model.Logo,
|
||||
@@ -97,3 +100,15 @@ func (m *Model) LLMs() []*provider.LLM {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *Model) LLM(id string) (*provider.LLM, bool) {
|
||||
model, has := m.models.Get(id)
|
||||
if !has {
|
||||
return nil, false
|
||||
}
|
||||
return &provider.LLM{
|
||||
Id: model.Id,
|
||||
Logo: model.Logo,
|
||||
Scopes: model.Scopes,
|
||||
}, true
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ type IAIProvider interface {
|
||||
InvokeConfig() IAIConfig
|
||||
UpdateLLMs() error
|
||||
LLMs() []*LLM
|
||||
LLM(id string) (*LLM, bool)
|
||||
}
|
||||
|
||||
type IAIConfig interface {
|
||||
|
||||
@@ -29,7 +29,6 @@ func (i *imlAPIDocModule) UpdateDoc(ctx context.Context, serviceId string, input
|
||||
}
|
||||
err = i.apiDocService.UpdateDoc(ctx, serviceId, &api_doc.UpdateDoc{
|
||||
ID: input.Id,
|
||||
Service: serviceId,
|
||||
Content: input.Content,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user