Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app-builder/plugins/aipp-custom-model-center/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
<groupId>modelengine.fit.jade.service</groupId>
<artifactId>tool-service</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,18 @@ public interface ModelMapper {
* @return 模型信息列表 {@link List}{@code <}{@link ModelPo}{@code >}.
*/
List<ModelPo> listModels(List<String> modelIds);

/**
* 插入模型信息。
Comment thread
CodeCasterX marked this conversation as resolved.
*
* @param model 模型对象。
*/
void insertModel(ModelPo model);

/**
* 根据模型ID删除模型信息。
*
* @param modelId 模型ID。
*/
void deleteByModelId(String modelId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import modelengine.fit.jade.aipp.model.po.UserModelPo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

Expand All @@ -34,4 +35,43 @@ public interface UserModelMapper {
* @return 默认的用户模型关系。
*/
UserModelPo getDefault(String userId);

/**
* 判断该用户是否已有模型绑定记录。
*
* @param userId 用户标识。
* @return true 表示已有模型,false 表示无记录。
*/
boolean userHasDefaultModel(String userId);
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated

/**
* 插入用户模型绑定关系。
*
* @param userModel 用户模型关系对象。
*/
void addUserModel(UserModelPo userModel);

/**
* 根据模型ID删除用户模型绑定关系。
*
* @param modelId 模型ID。
*/
void deleteByModelId(String modelId);

/**
* 查找指定用户最新创建的模型记录(按 created_at 降序排序,取第一条)。
* @param userId 用户标识。
*/
UserModelPo findLatestUserModel(String userId);

/**
* 将指定用户所有模型记录的 is_default 状态更新,
* 如果记录的 model_id 等于传入的 modelId,则设置为 1,否则设置为 0。
*
* @param userId 用户ID
* @param modelId 模型ID
* @return 更新的记录数
*/
int switchDefaultForUser(@Param("userId") String userId, @Param("modelId") String modelId);
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

package modelengine.fit.jade.aipp.model.po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import modelengine.jade.common.po.BasePo;

/**
Expand All @@ -16,6 +18,8 @@
* @since 2025/3/11
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
public class UserModelPo extends BasePo {
private String userId;
private String modelId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package modelengine.fit.jade.aipp.model.repository;
Comment thread
CodeCasterX marked this conversation as resolved.
Outdated

import modelengine.fit.jade.aipp.model.po.UserModelDetailPo;
import modelengine.fitframework.annotation.Genericable;
import modelengine.fitframework.annotation.Property;
import modelengine.jade.carver.tool.annotation.Group;
import modelengine.jade.carver.tool.annotation.ToolMethod;

import java.util.List;

/**
* 表示用户模型信息用于插件的持久化层的接口。
*
* @author lizhichao
* @since 2025/4/9
*/
@Group(name = "User_Model_Tool")
public interface UserModelPluginRepo {
/**
* 根据用户标识来查询该用户可用的用戶模型列表。
*
* @param userId 表示用户标识。
* @return 表示该用户可用的用戶模型列表 {@link List}{@code <}{@link UserModelDetailPo}{@code >}。
*/
@ToolMethod(name = "get_user_model_list", description = "根据用户标识来查询该用户可用的用戶模型列表")
@Genericable(id = "modelengine.fit.jade.aipp.model.getUserModelList")
List<UserModelDetailPo> getUserModelList(@Property(description = "用户id", required = true) String userId);

/**
* 为用户添加模型。
*
* @param userId 表示用户标识。
* @param apiKey 表示该用户访问模型所需的 API Key。
* @param modelName 表示模型名称。
* @param baseUrl 表示模型访问的地址。
* @return 添加结果提示信息。
*/
@ToolMethod(name = "add_user_model", description = "为用户添加可用的模型信息")
@Genericable(id = "modelengine.fit.jade.userModel.addUserModel")
String addUserModel(
@Property(description = "用户id", required = true) String userId,
@Property(description = "模型访问的 API Key", required = true) String apiKey,
@Property(description = "模型名称", required = true) String modelName,
@Property(description = "模型访问地址", required = true) String baseUrl
);

/**
* 删除用户绑定的模型信息。
*
* @param userId 表示用户标识。
* @param modelId 表示待删除的模型标识。
* @return 删除结果提示信息。
*/
@ToolMethod(name = "delete_user_model", description = "删除用户绑定的模型信息")
@Genericable(id = "modelengine.fit.jade.userModel.deleteUserModel")
String deleteUserModel(
@Property(description = "用户id", required = true) String userId,
@Property(description = "模型id", required = true) String modelId
);

/**
* 将指定模型设置为该用户的默认模型。
*
* @param userId 表示用户标识。
* @param modelId 表示要设为默认的模型标识。
* @return 切换默认模型的提示信息。
*/
@ToolMethod(name = "switch_default_model", description = "将指定模型设置为用户的默认模型")
@Genericable(id = "modelengine.fit.jade.userModel.switchDefaultModel")
String switchDefaultModel(
@Property(description = "用户id", required = true) String userId,
@Property(description = "默认模型id", required = true) String modelId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package modelengine.fit.jade.aipp.model.repository.impl;
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated

import modelengine.fit.jade.aipp.model.mapper.ModelMapper;
import modelengine.fit.jade.aipp.model.mapper.UserModelMapper;
import modelengine.fit.jade.aipp.model.po.ModelPo;
import modelengine.fit.jade.aipp.model.po.UserModelDetailPo;
import modelengine.fit.jade.aipp.model.po.UserModelPo;
import modelengine.fit.jade.aipp.model.repository.UserModelPluginRepo;
import modelengine.fit.jade.aipp.model.repository.UserModelRepo;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fitable;
import modelengine.fitframework.annotation.Property;
import modelengine.fitframework.log.Logger;
import modelengine.fitframework.util.CollectionUtils;
import modelengine.jade.carver.tool.annotation.Attribute;
import modelengine.jade.carver.tool.annotation.Group;
import modelengine.jade.carver.tool.annotation.ToolMethod;

import java.util.*;
import java.util.stream.Collectors;

/**
* 表示用户模型信息用于插件的持久化层的接口 {@link UserModelRepo} 的实现。
*
* @author lizhichao
* @since 2025/4/9
*/
@Component
@Group(name = "User_Model_Tool_Impl")
public class UserModelPluginRepoImpl implements UserModelPluginRepo {
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
private static final Logger log = Logger.get(UserModelRepoImpl.class);
private static final String FITABLE_ID = "aipp.model.repository";
public static final String DEFAULT_MODEL_TYPE = "chat_completions";
private final ModelMapper modelMapper;
private final UserModelMapper userModelMapper;

/**
* 构造方法。
*
* @param modelMapper 模型信息表的 MyBatis 映射接口,用于处理模型增删查改。
* @param userModelMapper 用户与模型绑定关系的 MyBatis 映射接口,用于管理用户模型映射数据。
*/
public UserModelPluginRepoImpl(ModelMapper modelMapper, UserModelMapper userModelMapper) {
this.modelMapper = modelMapper;
this.userModelMapper = userModelMapper;
}

@Override
@Fitable(id = FITABLE_ID)
@ToolMethod(name = "获取用户模型列表", description = "根据用户标识来查询该用户可用的模型列表", extensions = {
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
})
@Property(description = "返回该用户可用的模型列表")
public List<UserModelDetailPo> getUserModelList(String userId) {
log.info("start get model list for {}.", userId);
List<UserModelPo> userModelPos = this.userModelMapper.listUserModels(userId);
if (CollectionUtils.isEmpty(userModelPos)) {
log.warn("No user model records found for userId={}.", userId);
return Collections.emptyList();
}
List<String> modelIds = userModelPos.stream()
.map(UserModelPo::getModelId)
.distinct()
.collect(Collectors.toList());
List<ModelPo> modelPos = this.modelMapper.listModels(modelIds);
// 构建 modelId → ModelPo 映射
Map<String, ModelPo> modelMap = modelPos.stream()
.map(model -> Map.entry(model.getModelId(), model))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a
));
return userModelPos.stream().map(userModel -> {
ModelPo model = modelMap.get(userModel.getModelId());
return new UserModelDetailPo(
userModel.getCreatedAt(),
userModel.getModelId(),
userModel.getUserId(),
model != null ? model.getName() : null,
model != null ? model.getBaseUrl() : null,
userModel.getIsDefault()
);
}).collect(Collectors.toList());
}

@Override
@Fitable(id = FITABLE_ID)
@ToolMethod(name = "添加模型", description = "为用户添加可用的模型信息", extensions = {
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
})
@Property(description = "为用户添加可用的模型信息")
public String addUserModel(String userId, String apiKey,
String modelName, String baseUrl) {
log.info("start add user model for {}.", userId);
String modelId = UUID.randomUUID().toString().replace("-", "");
int isDefault = this.userModelMapper.userHasDefaultModel(userId) ? 0 : 1;

ModelPo modelPo = new ModelPo(modelId, modelName, modelId, baseUrl, DEFAULT_MODEL_TYPE);
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
modelPo.setCreatedBy(userId);
modelPo.setUpdatedBy(userId);
this.modelMapper.insertModel(modelPo);

UserModelPo userModelPo = new UserModelPo(userId, modelId, apiKey, isDefault);
userModelPo.setCreatedBy(userId);
userModelPo.setUpdatedBy(userId);
this.userModelMapper.addUserModel(userModelPo);
return "添加模型成功。";
Comment thread
lizhichao51 marked this conversation as resolved.
}

@Override
@Fitable(id = FITABLE_ID)
@ToolMethod(name = "删除模型", description = "删除用户绑定的模型信息", extensions = {
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
})
@Property(description = "删除用户绑定的模型信息")
public String deleteUserModel(String userId, String modelId) {
Comment thread
lizhichao51 marked this conversation as resolved.
log.info("start delete user model for {}.", userId);
List<UserModelPo> userModels = this.userModelMapper.listUserModels(userId);
if (userModels == null || userModels.isEmpty()) {
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
return "删除模型失败,当前用户没有任何模型记录。";
}

UserModelPo target = userModels.stream()
.filter(m -> Objects.equals(m.getModelId(), modelId))
.findFirst()
.orElse(null);
if (target == null) {
return "删除模型失败,该模型不属于当前用户。";
}
this.userModelMapper.deleteByModelId(modelId);
this.modelMapper.deleteByModelId(modelId);
// 如果删除的不是默认模型,直接返回
if (target.getIsDefault() != 1) {
return "删除模型成功。";
}
userModels.remove(target);
// 如果没有默认模型,但还有其他记录,则设置最新创建的为默认
if (!userModels.isEmpty()) {
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
UserModelPo latest = userModels.stream()
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
.max(Comparator.comparing(UserModelPo::getCreatedAt))
.orElse(null);
this.userModelMapper.switchDefaultForUser(userId, latest.getModelId());
return String.format("删除默认模型成功,添加%s为默认模型。", this.modelMapper.get(latest.getModelId()).getName());
}
return "删除模型成功,当前无默认模型。";
}

@Override
@Fitable(id = FITABLE_ID)
@ToolMethod(name = "切换默认模型", description = "将指定模型设置为用户的默认模型", extensions = {
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
})
@Property(description = "将指定模型设置为用户的默认模型")
public String switchDefaultModel(String userId, String modelId) {
log.info("start switch default model for {}.", userId);
int rows = this.userModelMapper.switchDefaultForUser(userId, modelId);
if (rows == 0) {
return "未查到对应模型。";
}
return String.format("已切换%s为默认模型。", this.modelMapper.get(modelId).getName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@
#{item}
</foreach>
</select>

<insert id="insertModel" parameterType="modelengine.fit.jade.aipp.model.po.ModelPo">
INSERT INTO t_app_engine_model (model_id, name, tag, base_url, type, created_by, updated_by)
VALUES (#{modelId}, #{name}, #{tag}, #{baseUrl}, #{type}, #{createdBy}, #{updatedBy})
</insert>

<delete id="deleteByModelId">
DELETE FROM t_app_engine_model
WHERE model_id = #{modelId}
</delete>
</mapper>
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,37 @@
where user_id = #{userId}
Comment thread
lizhichao51 marked this conversation as resolved.
Outdated
and is_default = 1
</select>

<select id="userHasDefaultModel" resultType="boolean">
SELECT EXISTS (
SELECT 1
FROM t_app_engine_user_model
WHERE user_id = #{userId}
AND is_default = 1
)
</select>

<insert id="addUserModel" parameterType="modelengine.fit.jade.aipp.model.po.UserModelPo">
INSERT INTO t_app_engine_user_model (user_id, model_id, api_key, is_default, created_by, updated_by)
VALUES (#{userId}, #{modelId}, #{apiKey}, #{isDefault}, #{createdBy}, #{updatedBy})
</insert>

<delete id="deleteByModelId">
DELETE FROM t_app_engine_user_model
WHERE model_id = #{modelId}
</delete>

<select id="findLatestUserModel" resultType="modelengine.fit.jade.aipp.model.po.UserModelPo">
SELECT user_id, model_id, api_key, is_default
FROM t_app_engine_user_model
WHERE user_id = #{userId}
ORDER BY created_at DESC
LIMIT 1
</select>

<update id="switchDefaultForUser" parameterType="map">
UPDATE t_app_engine_user_model
SET is_default = CASE WHEN model_id = #{modelId} THEN 1 ELSE 0 END
WHERE user_id = #{userId}
</update>
</mapper>
Loading