Skip to content

Commit 581ca3a

Browse files
committed
[app-platform] 新增用户对于模型列表增删改查接口
1 parent 7c652bd commit 581ca3a

File tree

8 files changed

+342
-0
lines changed

8 files changed

+342
-0
lines changed

app-builder/plugins/aipp-custom-model-center/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565
<artifactId>assertj-core</artifactId>
6666
<scope>test</scope>
6767
</dependency>
68+
<dependency>
69+
<groupId>modelengine.fit.jade.service</groupId>
70+
<artifactId>tool-service</artifactId>
71+
</dependency>
6872
</dependencies>
6973

7074
<build>

app-builder/plugins/aipp-custom-model-center/src/main/java/modelengine/fit/jade/aipp/model/mapper/ModelMapper.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,18 @@ public interface ModelMapper {
3434
* @return 模型信息列表 {@link List}{@code <}{@link ModelPo}{@code >}.
3535
*/
3636
List<ModelPo> listModels(List<String> modelIds);
37+
38+
/**
39+
* 插入模型信息。
40+
*
41+
* @param model 模型对象。
42+
*/
43+
void insertModel(ModelPo model);
44+
45+
/**
46+
* 根据模型ID删除模型信息。
47+
*
48+
* @param modelId 模型ID。
49+
*/
50+
void deleteByModelId(String modelId);
3751
}

app-builder/plugins/aipp-custom-model-center/src/main/java/modelengine/fit/jade/aipp/model/mapper/UserModelMapper.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import modelengine.fit.jade.aipp.model.po.UserModelPo;
1010
import org.apache.ibatis.annotations.Mapper;
11+
import org.apache.ibatis.annotations.Param;
1112

1213
import java.util.List;
1314

@@ -34,4 +35,43 @@ public interface UserModelMapper {
3435
* @return 默认的用户模型关系。
3536
*/
3637
UserModelPo getDefault(String userId);
38+
39+
/**
40+
* 判断该用户是否已有模型绑定记录。
41+
*
42+
* @param userId 用户标识。
43+
* @return true 表示已有模型,false 表示无记录。
44+
*/
45+
boolean userHasDefaultModel(String userId);
46+
47+
/**
48+
* 插入用户模型绑定关系。
49+
*
50+
* @param userModel 用户模型关系对象。
51+
*/
52+
void addUserModel(UserModelPo userModel);
53+
54+
/**
55+
* 根据模型ID删除用户模型绑定关系。
56+
*
57+
* @param modelId 模型ID。
58+
*/
59+
void deleteByModelId(String modelId);
60+
61+
/**
62+
* 查找指定用户最新创建的模型记录(按 created_at 降序排序,取第一条)。
63+
* @param userId 用户标识。
64+
*/
65+
UserModelPo findLatestUserModel(String userId);
66+
67+
/**
68+
* 将指定用户所有模型记录的 is_default 状态更新,
69+
* 如果记录的 model_id 等于传入的 modelId,则设置为 1,否则设置为 0。
70+
*
71+
* @param userId 用户ID
72+
* @param modelId 模型ID
73+
* @return 更新的记录数
74+
*/
75+
int switchDefaultForUser(@Param("userId") String userId, @Param("modelId") String modelId);
76+
3777
}

app-builder/plugins/aipp-custom-model-center/src/main/java/modelengine/fit/jade/aipp/model/po/UserModelPo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

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

9+
import lombok.AllArgsConstructor;
910
import lombok.Data;
11+
import lombok.EqualsAndHashCode;
1012
import modelengine.jade.common.po.BasePo;
1113

1214
/**
@@ -16,6 +18,8 @@
1618
* @since 2025/3/11
1719
*/
1820
@Data
21+
@EqualsAndHashCode(callSuper = true)
22+
@AllArgsConstructor
1923
public class UserModelPo extends BasePo {
2024
private String userId;
2125
private String modelId;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package modelengine.fit.jade.aipp.model.repository;
2+
3+
import modelengine.fit.jade.aipp.model.po.UserModelDetailPo;
4+
import modelengine.fitframework.annotation.Genericable;
5+
import modelengine.fitframework.annotation.Property;
6+
import modelengine.jade.carver.tool.annotation.Group;
7+
import modelengine.jade.carver.tool.annotation.ToolMethod;
8+
9+
import java.util.List;
10+
11+
/**
12+
* 表示用户模型信息用于插件的持久化层的接口。
13+
*
14+
* @author lizhichao
15+
* @since 2025/4/9
16+
*/
17+
@Group(name = "User_Model_Tool")
18+
public interface UserModelPluginRepo {
19+
/**
20+
* 根据用户标识来查询该用户可用的用戶模型列表。
21+
*
22+
* @param userId 表示用户标识。
23+
* @return 表示该用户可用的用戶模型列表 {@link List}{@code <}{@link UserModelDetailPo}{@code >}。
24+
*/
25+
@ToolMethod(name = "get_user_model_list", description = "根据用户标识来查询该用户可用的用戶模型列表")
26+
@Genericable(id = "modelengine.fit.jade.aipp.model.getUserModelList")
27+
List<UserModelDetailPo> getUserModelList(@Property(description = "用户id", required = true) String userId);
28+
29+
/**
30+
* 为用户添加模型。
31+
*
32+
* @param userId 表示用户标识。
33+
* @param apiKey 表示该用户访问模型所需的 API Key。
34+
* @param modelName 表示模型名称。
35+
* @param baseUrl 表示模型访问的地址。
36+
* @return 添加结果提示信息。
37+
*/
38+
@ToolMethod(name = "add_user_model", description = "为用户添加可用的模型信息")
39+
@Genericable(id = "modelengine.fit.jade.userModel.addUserModel")
40+
String addUserModel(
41+
@Property(description = "用户id", required = true) String userId,
42+
@Property(description = "模型访问的 API Key", required = true) String apiKey,
43+
@Property(description = "模型名称", required = true) String modelName,
44+
@Property(description = "模型访问地址", required = true) String baseUrl
45+
);
46+
47+
/**
48+
* 删除用户绑定的模型信息。
49+
*
50+
* @param userId 表示用户标识。
51+
* @param modelId 表示待删除的模型标识。
52+
* @return 删除结果提示信息。
53+
*/
54+
@ToolMethod(name = "delete_user_model", description = "删除用户绑定的模型信息")
55+
@Genericable(id = "modelengine.fit.jade.userModel.deleteUserModel")
56+
String deleteUserModel(
57+
@Property(description = "用户id", required = true) String userId,
58+
@Property(description = "模型id", required = true) String modelId
59+
);
60+
61+
/**
62+
* 将指定模型设置为该用户的默认模型。
63+
*
64+
* @param userId 表示用户标识。
65+
* @param modelId 表示要设为默认的模型标识。
66+
* @return 切换默认模型的提示信息。
67+
*/
68+
@ToolMethod(name = "switch_default_model", description = "将指定模型设置为用户的默认模型")
69+
@Genericable(id = "modelengine.fit.jade.userModel.switchDefaultModel")
70+
String switchDefaultModel(
71+
@Property(description = "用户id", required = true) String userId,
72+
@Property(description = "默认模型id", required = true) String modelId
73+
);
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package modelengine.fit.jade.aipp.model.repository.impl;
2+
3+
import modelengine.fit.jade.aipp.model.mapper.ModelMapper;
4+
import modelengine.fit.jade.aipp.model.mapper.UserModelMapper;
5+
import modelengine.fit.jade.aipp.model.po.ModelPo;
6+
import modelengine.fit.jade.aipp.model.po.UserModelDetailPo;
7+
import modelengine.fit.jade.aipp.model.po.UserModelPo;
8+
import modelengine.fit.jade.aipp.model.repository.UserModelPluginRepo;
9+
import modelengine.fit.jade.aipp.model.repository.UserModelRepo;
10+
import modelengine.fitframework.annotation.Component;
11+
import modelengine.fitframework.annotation.Fitable;
12+
import modelengine.fitframework.annotation.Property;
13+
import modelengine.fitframework.log.Logger;
14+
import modelengine.fitframework.util.CollectionUtils;
15+
import modelengine.jade.carver.tool.annotation.Attribute;
16+
import modelengine.jade.carver.tool.annotation.Group;
17+
import modelengine.jade.carver.tool.annotation.ToolMethod;
18+
19+
import java.util.*;
20+
import java.util.stream.Collectors;
21+
22+
/**
23+
* 表示用户模型信息用于插件的持久化层的接口 {@link UserModelRepo} 的实现。
24+
*
25+
* @author lizhichao
26+
* @since 2025/4/9
27+
*/
28+
@Component
29+
@Group(name = "User_Model_Tool_Impl")
30+
public class UserModelPluginRepoImpl implements UserModelPluginRepo {
31+
private static final Logger log = Logger.get(UserModelRepoImpl.class);
32+
private static final String FITABLE_ID = "aipp.model.repository";
33+
public static final String DEFAULT_MODEL_TYPE = "chat_completions";
34+
private final ModelMapper modelMapper;
35+
private final UserModelMapper userModelMapper;
36+
37+
/**
38+
* 构造方法。
39+
*
40+
* @param modelMapper 模型信息表的 MyBatis 映射接口,用于处理模型增删查改。
41+
* @param userModelMapper 用户与模型绑定关系的 MyBatis 映射接口,用于管理用户模型映射数据。
42+
*/
43+
public UserModelPluginRepoImpl(ModelMapper modelMapper, UserModelMapper userModelMapper) {
44+
this.modelMapper = modelMapper;
45+
this.userModelMapper = userModelMapper;
46+
}
47+
48+
@Override
49+
@Fitable(id = FITABLE_ID)
50+
@ToolMethod(name = "获取用户模型列表", description = "根据用户标识来查询该用户可用的模型列表", extensions = {
51+
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
52+
})
53+
@Property(description = "返回该用户可用的模型列表")
54+
public List<UserModelDetailPo> getUserModelList(String userId) {
55+
log.info("start get model list for {}.", userId);
56+
List<UserModelPo> userModelPos = this.userModelMapper.listUserModels(userId);
57+
if (CollectionUtils.isEmpty(userModelPos)) {
58+
log.warn("No user model records found for userId={}.", userId);
59+
return Collections.emptyList();
60+
}
61+
List<String> modelIds = userModelPos.stream()
62+
.map(UserModelPo::getModelId)
63+
.distinct()
64+
.collect(Collectors.toList());
65+
List<ModelPo> modelPos = this.modelMapper.listModels(modelIds);
66+
// 构建 modelId → ModelPo 映射
67+
Map<String, ModelPo> modelMap = modelPos.stream()
68+
.map(model -> Map.entry(model.getModelId(), model))
69+
.collect(Collectors.toMap(
70+
Map.Entry::getKey,
71+
Map.Entry::getValue,
72+
(a, b) -> a
73+
));
74+
return userModelPos.stream().map(userModel -> {
75+
ModelPo model = modelMap.get(userModel.getModelId());
76+
return new UserModelDetailPo(
77+
userModel.getCreatedAt(),
78+
userModel.getModelId(),
79+
userModel.getUserId(),
80+
model != null ? model.getName() : null,
81+
model != null ? model.getBaseUrl() : null,
82+
userModel.getIsDefault()
83+
);
84+
}).collect(Collectors.toList());
85+
}
86+
87+
@Override
88+
@Fitable(id = FITABLE_ID)
89+
@ToolMethod(name = "添加模型", description = "为用户添加可用的模型信息", extensions = {
90+
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
91+
})
92+
@Property(description = "为用户添加可用的模型信息")
93+
public String addUserModel(String userId, String apiKey,
94+
String modelName, String baseUrl) {
95+
log.info("start add user model for {}.", userId);
96+
String modelId = UUID.randomUUID().toString().replace("-", "");
97+
int isDefault = this.userModelMapper.userHasDefaultModel(userId) ? 0 : 1;
98+
99+
ModelPo modelPo = new ModelPo(modelId, modelName, modelId, baseUrl, DEFAULT_MODEL_TYPE);
100+
modelPo.setCreatedBy(userId);
101+
modelPo.setUpdatedBy(userId);
102+
this.modelMapper.insertModel(modelPo);
103+
104+
UserModelPo userModelPo = new UserModelPo(userId, modelId, apiKey, isDefault);
105+
userModelPo.setCreatedBy(userId);
106+
userModelPo.setUpdatedBy(userId);
107+
this.userModelMapper.addUserModel(userModelPo);
108+
return "添加模型成功。";
109+
}
110+
111+
@Override
112+
@Fitable(id = FITABLE_ID)
113+
@ToolMethod(name = "删除模型", description = "删除用户绑定的模型信息", extensions = {
114+
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
115+
})
116+
@Property(description = "删除用户绑定的模型信息")
117+
public String deleteUserModel(String userId, String modelId) {
118+
log.info("start delete user model for {}.", userId);
119+
List<UserModelPo> userModels = this.userModelMapper.listUserModels(userId);
120+
if (userModels == null || userModels.isEmpty()) {
121+
return "删除模型失败,当前用户没有任何模型记录。";
122+
}
123+
124+
UserModelPo target = userModels.stream()
125+
.filter(m -> Objects.equals(m.getModelId(), modelId))
126+
.findFirst()
127+
.orElse(null);
128+
if (target == null) {
129+
return "删除模型失败,该模型不属于当前用户。";
130+
}
131+
this.userModelMapper.deleteByModelId(modelId);
132+
this.modelMapper.deleteByModelId(modelId);
133+
// 如果删除的不是默认模型,直接返回
134+
if (target.getIsDefault() != 1) {
135+
return "删除模型成功。";
136+
}
137+
userModels.remove(target);
138+
// 如果没有默认模型,但还有其他记录,则设置最新创建的为默认
139+
if (!userModels.isEmpty()) {
140+
UserModelPo latest = userModels.stream()
141+
.max(Comparator.comparing(UserModelPo::getCreatedAt))
142+
.orElse(null);
143+
this.userModelMapper.switchDefaultForUser(userId, latest.getModelId());
144+
return String.format("删除默认模型成功,添加%s为默认模型。", this.modelMapper.get(latest.getModelId()).getName());
145+
}
146+
return "删除模型成功,当前无默认模型。";
147+
}
148+
149+
@Override
150+
@Fitable(id = FITABLE_ID)
151+
@ToolMethod(name = "切换默认模型", description = "将指定模型设置为用户的默认模型", extensions = {
152+
@Attribute(key = "tags", value = "FIT"), @Attribute(key = "tags", value = "MODEL")
153+
})
154+
@Property(description = "将指定模型设置为用户的默认模型")
155+
public String switchDefaultModel(String userId, String modelId) {
156+
log.info("start switch default model for {}.", userId);
157+
int rows = this.userModelMapper.switchDefaultForUser(userId, modelId);
158+
if (rows == 0) {
159+
return "未查到对应模型。";
160+
}
161+
return String.format("已切换%s为默认模型。", this.modelMapper.get(modelId).getName());
162+
}
163+
}

app-builder/plugins/aipp-custom-model-center/src/main/resources/mapper/ModelMapper.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,14 @@
2929
#{item}
3030
</foreach>
3131
</select>
32+
33+
<insert id="insertModel" parameterType="modelengine.fit.jade.aipp.model.po.ModelPo">
34+
INSERT INTO t_app_engine_model (model_id, name, tag, base_url, type, created_by, updated_by)
35+
VALUES (#{modelId}, #{name}, #{tag}, #{baseUrl}, #{type}, #{createdBy}, #{updatedBy})
36+
</insert>
37+
38+
<delete id="deleteByModelId">
39+
DELETE FROM t_app_engine_model
40+
WHERE model_id = #{modelId}
41+
</delete>
3242
</mapper>

app-builder/plugins/aipp-custom-model-center/src/main/resources/mapper/UserModelMapper.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,37 @@
2727
where user_id = #{userId}
2828
and is_default = 1
2929
</select>
30+
31+
<select id="userHasDefaultModel" resultType="boolean">
32+
SELECT EXISTS (
33+
SELECT 1
34+
FROM t_app_engine_user_model
35+
WHERE user_id = #{userId}
36+
AND is_default = 1
37+
)
38+
</select>
39+
40+
<insert id="addUserModel" parameterType="modelengine.fit.jade.aipp.model.po.UserModelPo">
41+
INSERT INTO t_app_engine_user_model (user_id, model_id, api_key, is_default, created_by, updated_by)
42+
VALUES (#{userId}, #{modelId}, #{apiKey}, #{isDefault}, #{createdBy}, #{updatedBy})
43+
</insert>
44+
45+
<delete id="deleteByModelId">
46+
DELETE FROM t_app_engine_user_model
47+
WHERE model_id = #{modelId}
48+
</delete>
49+
50+
<select id="findLatestUserModel" resultType="modelengine.fit.jade.aipp.model.po.UserModelPo">
51+
SELECT user_id, model_id, api_key, is_default
52+
FROM t_app_engine_user_model
53+
WHERE user_id = #{userId}
54+
ORDER BY created_at DESC
55+
LIMIT 1
56+
</select>
57+
58+
<update id="switchDefaultForUser" parameterType="map">
59+
UPDATE t_app_engine_user_model
60+
SET is_default = CASE WHEN model_id = #{modelId} THEN 1 ELSE 0 END
61+
WHERE user_id = #{userId}
62+
</update>
3063
</mapper>

0 commit comments

Comments
 (0)