Fix: Align part of Go provider APIs with Python APIs (#16823)

This commit is contained in:
Lynn
2026-07-13 11:20:02 +08:00
committed by GitHub
parent 3c0f8fc192
commit b0cac0ac9d
10 changed files with 498 additions and 21 deletions

View File

@@ -81,9 +81,9 @@ func TestGoogleScholar_InvokeMergesNodeParams(t *testing.T) {
fake := &fakeGoogleScholarInvoker{}
c := newGoogleScholarComponentWithInvoker(fake, map[string]any{
"top_n": float64(20),
"sort_by": "date",
"patents": false,
"top_n": float64(20),
"sort_by": "date",
"patents": false,
})
_, err := c.Invoke(context.Background(), map[string]any{

View File

@@ -834,7 +834,7 @@ Commands (User Mode):
USE MODEL 'provider/instance/model'; - Set current model for chat
CHAT 'message'; - Chat using current model
CHAT 'provider/instance/model' 'message'; - Chat with specified model
OPENAI_CHAT 'chat_id' 'message' [options] ; - OpenAI-compatible chat
OPENAI_CHAT 'chat_id' 'message' [options] ; - OpenAI-compatible chat
(run openai_chat -h for detailed options)
CHAT COMPLETIONS 'question' [options] ; - Chat completions via /api/v1/chat/completions
(run chat completions -h for detailed options)

View File

@@ -123,6 +123,31 @@ func (dao *TenantModelDAO) GetModelsByInstanceID(instanceID string) ([]*entity.T
return models, nil
}
// DeleteByIDs deletes all models whose id is in the given list.
// Mirrors Python's TenantModelService.delete_by_ids.
func (dao *TenantModelDAO) DeleteByIDs(ids []string) (int64, error) {
if len(ids) == 0 {
return 0, nil
}
result := DB.Unscoped().Where("id IN ?", ids).Delete(&entity.TenantModel{})
return result.RowsAffected, result.Error
}
// UpdateByID updates a tenant model's model_type and extra by primary key.
// Mirrors Python's TenantModelService.update_model.
func (dao *TenantModelDAO) UpdateByID(id string, updates map[string]interface{}) error {
return DB.Model(&entity.TenantModel{}).Where("id = ?", id).Updates(updates).Error
}
// DeleteByInstanceIDs deletes all models whose instance_id is in the given list.
func (dao *TenantModelDAO) DeleteByInstanceIDs(instanceIDs []string) (int64, error) {
if len(instanceIDs) == 0 {
return 0, nil
}
result := DB.Unscoped().Where("instance_id IN ?", instanceIDs).Delete(&entity.TenantModel{})
return result.RowsAffected, result.Error
}
// GetModelsByProviderIDsAndInstanceIDs returns TenantModel rows whose
// provider_id is in providerIDs and instance_id is in instanceIDs.
// Mirrors Python's

View File

@@ -110,3 +110,15 @@ func (dao *TenantModelInstanceDAO) DeleteByProviderIDAndInstanceName(providerID,
result := DB.Unscoped().Where("provider_id = ? and instance_name = ?", providerID, instanceName).Delete(&entity.TenantModelInstance{})
return result.RowsAffected, result.Error
}
// UpdateByID updates a tenant model instance by primary key.
// Mirrors Python's TenantModelInstanceService.update_by_id.
func (dao *TenantModelInstanceDAO) UpdateByID(id string, updates map[string]interface{}) error {
return DB.Model(&entity.TenantModelInstance{}).Where("id = ?", id).Updates(updates).Error
}
// DeleteByProviderID deletes all instances for the given provider.
func (dao *TenantModelInstanceDAO) DeleteByProviderID(providerID string) (int64, error) {
result := DB.Unscoped().Where("provider_id = ?", providerID).Delete(&entity.TenantModelInstance{})
return result.RowsAffected, result.Error
}

View File

@@ -141,3 +141,11 @@ func ModelTypeFromStrings(types []string) ModelType {
}
return result
}
// ModelVerifyStatus mirrors Python's ModelVerifyStatusEnum
// (common/constants.py).
const (
ModelVerifySuccess = "success"
ModelVerifyFail = "fail"
ModelVerifyUnknown = "unknown"
)

View File

@@ -175,10 +175,11 @@ func (h *ProviderHandler) ShowModel(c *gin.Context) {
}
type CreateProviderInstanceRequest struct {
InstanceName string `json:"instance_name" binding:"required"`
APIKey string `json:"api_key"`
BaseURL string `json:"base_url"`
Region string `json:"region"`
InstanceName string `json:"instance_name" binding:"required"`
APIKey string `json:"api_key"`
BaseURL string `json:"base_url"`
Region string `json:"region"`
ModelInfo []service.CreateInstanceModelInfo `json:"model_info"`
}
func (h *ProviderHandler) CreateProviderInstance(c *gin.Context) {
@@ -196,7 +197,20 @@ func (h *ProviderHandler) CreateProviderInstance(c *gin.Context) {
userID := c.GetString("user_id")
_, err := h.modelProviderService.CreateProviderInstance(providerName, req.InstanceName, req.APIKey, req.BaseURL, req.Region, userID)
// If the request body only contains "instance_name", create a name-only
// instance without API key validation or model creation.
// Mirrors Python's provider_api.py:349 — set(data.keys()) == {"instance_name"}.
if req.APIKey == "" && req.BaseURL == "" && req.Region == "" && len(req.ModelInfo) == 0 {
code, err := h.modelProviderService.CreateNameOnlyProviderInstance(providerName, req.InstanceName, userID)
if err != nil {
common.ErrorWithCode(c, code, err.Error())
return
}
common.SuccessWithMessage(c, "success")
return
}
_, err := h.modelProviderService.CreateProviderInstance(providerName, req.InstanceName, req.APIKey, req.BaseURL, req.Region, userID, req.ModelInfo)
if err != nil {
common.ErrorWithCode(c, common.CodeServerError, err.Error())
return
@@ -388,8 +402,12 @@ func (h *ProviderHandler) ShowTask(c *gin.Context) {
}
type AlterProviderInstanceRequest struct {
InstanceName string `json:"instance_name"`
APIKey string `json:"api_key"`
InstanceName string `json:"instance_name"`
APIKey string `json:"api_key"`
BaseURL string `json:"base_url"`
Region string `json:"region"`
ModelInfo []service.CreateInstanceModelInfo `json:"model_info"`
Verify *bool `json:"verify"`
}
func (h *ProviderHandler) AlterProviderInstance(c *gin.Context) {
@@ -417,7 +435,12 @@ func (h *ProviderHandler) AlterProviderInstance(c *gin.Context) {
return
}
code, err := h.modelProviderService.AlterProviderInstance(userID, providerName, instanceName, req.InstanceName, req.APIKey)
verify := true
if req.Verify != nil {
verify = *req.Verify
}
code, err := h.modelProviderService.AlterProviderInstance(userID, providerName, instanceName, req.InstanceName, req.APIKey, req.BaseURL, req.Region, req.ModelInfo, verify)
if err != nil {
common.ErrorWithCode(c, code, err.Error())
return

View File

@@ -228,12 +228,35 @@ func (m *ModelProviderService) ListProvidersOfTenant(userID string) ([]map[strin
return nil, common.CodeServerError, err
}
provider["name"] = providerName
// Set has_instance flag. Mirrors Python's:
// provider_obj = TenantModelProviderService.get_by_tenant_id_and_provider_name(tenant_id, name)
// has_instance = bool(provider_obj and TenantModelInstanceService.get_all_by_provider_id(provider_obj.id))
provider["has_instance"] = m.providerHasInstance(tenantID, providerName)
result = append(result, provider)
}
return result, common.CodeSuccess, nil
}
// providerHasInstance checks whether the given tenant's provider has any
// configured instances. Mirrors the Python pattern:
//
// provider_obj = TenantModelProviderService.get_by_tenant_id_and_provider_name(tenant_id, name)
// has_instance = bool(provider_obj and TenantModelInstanceService.get_all_by_provider_id(provider_obj.id))
func (m *ModelProviderService) providerHasInstance(tenantID, providerName string) bool {
providerObj, err := m.modelProviderDAO.GetByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return false
}
instances, err := m.modelInstanceDAO.GetAllInstancesByProviderID(providerObj.ID)
if err != nil {
return false
}
return len(instances) > 0
}
// isExcludedTenantProvider returns true for system-pool names that the Python
// implementation (api/apps/services/provider_api_service.py:108) intentionally
// filters out when listing a tenant's providers.
@@ -255,6 +278,30 @@ func (m *ModelProviderService) DeleteModelProvider(userID, providerName string)
}
tenantID := tenants[0].TenantID
// Find the provider first.
provider, err := m.modelProviderDAO.GetByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return common.CodeNotFound, fmt.Errorf("provider %s not found", providerName)
}
// Delete all models and instances under this provider.
instances, err := m.modelInstanceDAO.GetAllInstancesByProviderID(provider.ID)
if err != nil {
return common.CodeServerError, err
}
if len(instances) > 0 {
instanceIDs := make([]string, len(instances))
for i, inst := range instances {
instanceIDs[i] = inst.ID
}
if _, err := m.modelDAO.DeleteByInstanceIDs(instanceIDs); err != nil {
return common.CodeServerError, err
}
if _, err := m.modelInstanceDAO.DeleteByProviderID(provider.ID); err != nil {
return common.CodeServerError, err
}
}
_, err = m.modelProviderDAO.DeleteByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return common.CodeServerError, err
@@ -339,7 +386,16 @@ func (m *ModelProviderService) ListSupportedModels(providerName, instanceName, u
return result, nil
}
func (m *ModelProviderService) CreateProviderInstance(providerName, instanceName, apiKey, baseURL, region, userID string) (common.ErrorCode, error) {
// CreateInstanceModelInfo mirrors Python's model_info dict in
// create_provider_instance. See api/apps/services/provider_api_service.py:434.
type CreateInstanceModelInfo struct {
ModelName string `json:"model_name"`
ModelTypes []string `json:"model_type"`
MaxTokens int `json:"max_tokens"`
Extra map[string]interface{} `json:"extra"`
}
func (m *ModelProviderService) CreateProviderInstance(providerName, instanceName, apiKey, baseURL, region, userID string, modelInfo []CreateInstanceModelInfo) (common.ErrorCode, error) {
providerName = strings.TrimSpace(providerName)
providerName = strings.ToLower(providerName)
@@ -361,19 +417,28 @@ func (m *ModelProviderService) CreateProviderInstance(providerName, instanceName
return common.CodeServerError, err
}
// Normalize api_key: VLLM with empty api_key defaults to "x".
// Mirrors Python's _normalize_provider_api_key.
if strings.EqualFold(providerName, "vllm") && apiKey == "" {
apiKey = "x"
}
// Verify the API key against the provider.
// Mirrors Python's verify_api_key (provider_api_service.py:596).
modelVerifyResult := m.verifyProviderAPIKey(providerName, apiKey, region, baseURL, modelInfo)
instanceID := utility.GenerateToken()
extra := make(map[string]string)
extra["region"] = region
extra["base_url"] = baseURL
// convert extra to string
extraByte, err := json.Marshal(extra)
if err != nil {
return common.CodeServerError, errors.New("fail to marshal extra")
}
extraStr := string(extraByte)
tenantModelProvider := &entity.TenantModelInstance{
tenantModelInstance := &entity.TenantModelInstance{
ID: instanceID,
InstanceName: instanceName,
ProviderID: provider.ID,
@@ -381,14 +446,187 @@ func (m *ModelProviderService) CreateProviderInstance(providerName, instanceName
Status: "active",
Extra: extraStr,
}
err = m.modelInstanceDAO.Create(tenantModelProvider)
err = m.modelInstanceDAO.Create(tenantModelInstance)
if err != nil {
return common.CodeServerError, fmt.Errorf("fail to create model instance: %s", err.Error())
}
// Add models with verify result in extra.
if len(modelInfo) > 0 {
for _, model := range modelInfo {
if model.Extra == nil {
model.Extra = make(map[string]interface{})
}
verifyStatus := modelVerifyResult[model.ModelName]
if verifyStatus == "" {
verifyStatus = entity.ModelVerifyUnknown
}
model.Extra["verify"] = verifyStatus
if err := m.addModelToInstance(tenantID, providerName, instanceName, model); err != nil {
return common.CodeServerError, err
}
}
}
return common.CodeSuccess, nil
}
// CreateNameOnlyProviderInstance creates a provider instance with only a name,
// skipping API key validation and model creation. Mirrors Python's
// create_name_only_provider_instance in provider_api_service.py:536.
func (m *ModelProviderService) CreateNameOnlyProviderInstance(providerName, instanceName, userID string) (common.ErrorCode, error) {
providerName = strings.TrimSpace(providerName)
providerName = strings.ToLower(providerName)
if instanceName == "default" {
return common.CodeBadRequest, errors.New("instance name cannot be 'default'")
}
tenants, err := m.userTenantDAO.GetByUserIDAndRole(userID, "owner")
if err != nil {
return common.CodeServerError, err
}
if len(tenants) == 0 {
return common.CodeNotFound, errors.New("user has no tenants")
}
tenantID := tenants[0].TenantID
provider, err := m.modelProviderDAO.GetByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return common.CodeNotFound, fmt.Errorf("provider '%s' does not exist", providerName)
}
instanceID := utility.GenerateToken()
tenantModelInstance := &entity.TenantModelInstance{
ID: instanceID,
InstanceName: instanceName,
ProviderID: provider.ID,
APIKey: "",
Status: "active",
Extra: "{}",
}
err = m.modelInstanceDAO.Create(tenantModelInstance)
if err != nil {
return common.CodeServerError, fmt.Errorf("fail to create model instance: %s", err.Error())
}
return common.CodeSuccess, nil
}
// verifyProviderAPIKey verifies the API key against the provider by calling
// the driver's CheckConnection. It returns a map from model name to verify
// status (success/fail/unknown). Mirrors Python's verify_api_key in
// provider_api_service.py:596.
func (m *ModelProviderService) verifyProviderAPIKey(providerName, apiKey, region, baseURL string, modelInfo []CreateInstanceModelInfo) map[string]string {
result := make(map[string]string)
providerInfo := dao.GetModelProviderManager().FindProvider(providerName)
if providerInfo == nil {
// Provider not in system pool — mark all models as unknown.
for _, model := range modelInfo {
result[model.ModelName] = entity.ModelVerifyUnknown
}
return result
}
apiKey = strings.TrimSpace(apiKey)
region = strings.TrimSpace(region)
baseURL = strings.TrimSpace(baseURL)
if region == "" {
region = "default"
}
driver := providerInfo.ModelDriver
if strings.EqualFold(providerInfo.Class, "local") {
var err error
driver, err = newModelDriverForBaseURL(driver, providerName, region, baseURL)
if err != nil {
for _, model := range modelInfo {
result[model.ModelName] = entity.ModelVerifyFail
}
return result
}
}
apiConfig := &modelModule.APIConfig{
ApiKey: &apiKey,
Region: &region,
BaseURL: &baseURL,
}
verifyErr := driver.CheckConnection(apiConfig)
verifyStatus := entity.ModelVerifySuccess
if verifyErr != nil {
verifyStatus = entity.ModelVerifyFail
}
for _, model := range modelInfo {
result[model.ModelName] = verifyStatus
}
return result
}
// addModelToInstance creates a single model under the given provider instance.
// Mirrors Python's add_model_to_instance in provider_api_service.py:969.
func (m *ModelProviderService) addModelToInstance(tenantID, providerName, instanceName string, model CreateInstanceModelInfo) error {
provider, err := m.modelProviderDAO.GetByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return fmt.Errorf("no provider found for provider '%s'", providerName)
}
instance, err := m.modelInstanceDAO.GetByProviderIDAndInstanceName(provider.ID, instanceName)
if err != nil {
return fmt.Errorf("no instance found for provider '%s' and instance '%s'", providerName, instanceName)
}
// Check for duplicate model.
_, err = m.modelDAO.GetModelByProviderIDAndInstanceIDAndModelName(provider.ID, instance.ID, model.ModelName)
if err == nil {
return fmt.Errorf("model '%s' already exists for provider '%s' and instance '%s'", model.ModelName, providerName, instanceName)
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
// Compute model type bitmask.
combinedType := entity.ModelType(0)
for _, t := range model.ModelTypes {
combinedType |= entity.ModelTypeFromString(t)
}
// Build extra fields. Mirrors Python's extra_fields in add_model_to_instance.
extraFields := map[string]interface{}{
"max_tokens": model.MaxTokens,
}
if model.Extra != nil {
for k, v := range model.Extra {
extraFields[k] = v
}
}
extraBytes, err := json.Marshal(extraFields)
if err != nil {
return fmt.Errorf("fail to marshal extra: %s", err.Error())
}
modelID := utility.GenerateToken()
tenantModel := &entity.TenantModel{
ID: modelID,
ModelName: model.ModelName,
ModelType: int(combinedType),
ProviderID: provider.ID,
InstanceID: instance.ID,
Status: "active",
Extra: string(extraBytes),
}
if err := m.modelDAO.Create(tenantModel); err != nil {
return fmt.Errorf("fail to create model '%s': %s", model.ModelName, err.Error())
}
return nil
}
func (m *ModelProviderService) ListProviderInstances(providerName, userID string) ([]map[string]interface{}, common.ErrorCode, error) {
providerName = strings.TrimSpace(providerName)
providerName = strings.ToLower(providerName)
@@ -999,7 +1237,173 @@ func (m *ModelProviderService) resolveModelListTenant(userID, ownerTenantID stri
return tenant, common.CodeSuccess, nil
}
func (m *ModelProviderService) AlterProviderInstance(userID, providerName, instanceName, newInstanceName, apiKey string) (common.ErrorCode, error) {
func (m *ModelProviderService) AlterProviderInstance(userID, providerName, instanceIDOrName, newInstanceName, apiKey, baseURL, region string, modelInfo []CreateInstanceModelInfo, verify bool) (common.ErrorCode, error) {
providerName = strings.TrimSpace(providerName)
providerName = strings.ToLower(providerName)
tenants, err := m.userTenantDAO.GetByUserIDAndRole(userID, "owner")
if err != nil {
return common.CodeServerError, err
}
if len(tenants) == 0 {
return common.CodeNotFound, errors.New("user has no tenants")
}
tenantID := tenants[0].TenantID
provider, err := m.modelProviderDAO.GetByTenantIDAndProviderName(tenantID, providerName)
if err != nil {
return common.CodeNotFound, fmt.Errorf("provider '%s' does not exist", providerName)
}
// Find the instance — try by ID first, then by name.
instance, err := m.modelInstanceDAO.GetByID(instanceIDOrName)
if err != nil || instance.ProviderID != provider.ID {
instance, err = m.modelInstanceDAO.GetByProviderIDAndInstanceName(provider.ID, instanceIDOrName)
}
if err != nil {
return common.CodeNotFound, fmt.Errorf("no instance found for provider '%s' and instance '%s'", providerName, instanceIDOrName)
}
// Normalize api_key: VLLM with empty api_key defaults to "x".
if strings.EqualFold(providerName, "vllm") && apiKey == "" {
apiKey = "x"
}
// Verify API key if requested.
modelVerifyResult := make(map[string]string)
if verify {
modelVerifyResult = m.verifyProviderAPIKey(providerName, apiKey, region, baseURL, modelInfo)
}
// Update instance record.
instanceUpdates := map[string]interface{}{
"api_key": apiKey,
}
if newInstanceName != "" && newInstanceName != instance.InstanceName {
instanceUpdates["instance_name"] = newInstanceName
}
extraFields := make(map[string]interface{})
if baseURL != "" {
extraFields["base_url"] = baseURL
}
if region != "" {
extraFields["region"] = region
}
// Preserve existing extra fields not overwritten.
existingExtra := make(map[string]interface{})
if instance.Extra != "" {
if err := json.Unmarshal([]byte(instance.Extra), &existingExtra); err != nil {
return common.CodeServerError, err
}
}
for k, v := range extraFields {
existingExtra[k] = v
}
extraBytes, err := json.Marshal(existingExtra)
if err != nil {
return common.CodeServerError, err
}
instanceUpdates["extra"] = string(extraBytes)
if err := m.modelInstanceDAO.UpdateByID(instance.ID, instanceUpdates); err != nil {
return common.CodeServerError, fmt.Errorf("fail to update instance: %s", err.Error())
}
// Use the (possibly updated) instance_name for model operations.
effectiveInstanceName := instance.InstanceName
if newInstanceName != "" {
effectiveInstanceName = newInstanceName
}
// Upsert models: add new ones, update existing ones, remove ones no longer selected.
existingModels, err := m.modelDAO.GetModelsByInstanceID(instance.ID)
if err != nil {
return common.CodeServerError, err
}
existingModelMap := make(map[string]*entity.TenantModel)
for _, mdl := range existingModels {
existingModelMap[mdl.ModelName] = mdl
}
// Delete models that are no longer in the submitted model_info.
submittedModelNames := make(map[string]bool)
if modelInfo != nil {
for _, mdl := range modelInfo {
if mdl.ModelName != "" {
submittedModelNames[mdl.ModelName] = true
}
}
}
var idsToRemove []string
for name, mdl := range existingModelMap {
if !submittedModelNames[name] {
idsToRemove = append(idsToRemove, mdl.ID)
}
}
if len(idsToRemove) > 0 {
if _, err := m.modelDAO.DeleteByIDs(idsToRemove); err != nil {
return common.CodeServerError, err
}
}
// Add or update models from model_info.
if modelInfo != nil {
for _, mdl := range modelInfo {
if mdl.ModelName == "" {
continue
}
// Attach verify status.
if verify {
verifyStatus := modelVerifyResult[mdl.ModelName]
if verifyStatus == "" {
verifyStatus = entity.ModelVerifyUnknown
}
if mdl.Extra == nil {
mdl.Extra = make(map[string]interface{})
}
mdl.Extra["verify"] = verifyStatus
}
if existingMdl, exists := existingModelMap[mdl.ModelName]; exists {
// Update existing model.
updates := make(map[string]interface{})
if len(mdl.ModelTypes) > 0 {
combinedType := entity.ModelType(0)
for _, t := range mdl.ModelTypes {
combinedType |= entity.ModelTypeFromString(t)
}
if int(combinedType) != existingMdl.ModelType {
updates["model_type"] = int(combinedType)
}
}
mergedExtra := make(map[string]interface{})
if existingMdl.Extra != "" {
json.Unmarshal([]byte(existingMdl.Extra), &mergedExtra)
}
if mdl.Extra != nil {
for k, v := range mdl.Extra {
mergedExtra[k] = v
}
}
if mdl.MaxTokens > 0 {
mergedExtra["max_tokens"] = mdl.MaxTokens
}
extraBytes, _ := json.Marshal(mergedExtra)
updates["extra"] = string(extraBytes)
if len(updates) > 0 {
if err := m.modelDAO.UpdateByID(existingMdl.ID, updates); err != nil {
return common.CodeServerError, err
}
}
} else {
// Add new model.
if err := m.addModelToInstance(tenantID, providerName, effectiveInstanceName, mdl); err != nil {
return common.CodeServerError, err
}
}
}
}
return common.CodeSuccess, nil
}

View File

@@ -2401,7 +2401,8 @@ Best for: Documents with flowing, contextually connected content — such as boo
bGPTDescription:
'Search scientific papers via BGPT and return structured evidence from full-text studies: methods, sample sizes, limitations, conflicts of interest, data availability, blind spots, and falsification prompts. Optional API key after the free tier.',
bgptApiKey: 'API key',
bgptApiKeyTip: 'Optional. Leave blank for the free tier (first 50 results).',
bgptApiKeyTip:
'Optional. Leave blank for the free tier (first 50 results).',
bgptDaysBack: 'Days back',
bgptDaysBackTip: 'Optional recency filter (e.g. 365 for the last year).',
email: 'Email',

View File

@@ -38,7 +38,9 @@ const CompilationForm = ({ node }: INextOperatorForm) => {
return (
<Form {...form}>
<FormWrapper>
<LargeModelFormField ownerTenantId={ownerTenantId}></LargeModelFormField>
<LargeModelFormField
ownerTenantId={ownerTenantId}
></LargeModelFormField>
<CompilationTemplateFormField name="compilation_template_group_ids"></CompilationTemplateFormField>
<Output list={outputList}></Output>
</FormWrapper>

View File

@@ -29,7 +29,9 @@ export function LLMSelectForm() {
return (
<Form {...form}>
<LargeModelFormFieldWithoutFilter ownerTenantId={data?.tenant_id}></LargeModelFormFieldWithoutFilter>
<LargeModelFormFieldWithoutFilter
ownerTenantId={data?.tenant_id}
></LargeModelFormFieldWithoutFilter>
</Form>
);
}