Skip to content

新增北向接口 #324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
14c296e
[app-platform] 新增apikey-service
Jul 7, 2025
7bf8808
[app-platform] 新增apikey-auth-default插件
Jul 7, 2025
4967590
[app-platform] 新增apikey-auth-oms插件
Jul 7, 2025
20e19e7
[app-platform] 修改apikey-service pom文件
Jul 8, 2025
803ef2b
[app-platform] 修改apikey插件 pom文件
Jul 8, 2025
9668a84
[app-platform] 修改apikey-auth-default插件application文件
Jul 8, 2025
d47a382
[app-platform] 新增NorthFilter
Jul 8, 2025
8e35f4a
[app-platform] 修改LoginFilter mismatch条件
Jul 8, 2025
da9c27b
[app-platform] 更新已有北向接口请求前缀
Jul 8, 2025
8993e42
[app-platform] 新增用户反馈相关的北向接口
Jul 8, 2025
5e83d1d
[app-platform] 新增会话历史相关的北向接口
Jul 9, 2025
ff3f8d5
[app-platform] 修改会话历史相关的北向接口groupName
Jul 11, 2025
b89315c
[app-platform] OmsApikeyAuthService修改ssl解码问题
Jul 11, 2025
08e5741
[app-platform] 修复北向对话接口参数转换问题
Jul 15, 2025
04b0f20
[app-platform] 修复北向查询应用列表参数问题
Jul 15, 2025
1ef85ea
[app-platform] 修复北向删除会话参数名
Jul 15, 2025
498b114
[app-platform] 去除北向会话接口参数默认值
Jul 15, 2025
689c69e
[app-platform] 修复换行符问题
Jul 16, 2025
0b04efa
[app-platform] 检视意见修改
Jul 16, 2025
61cb98b
[app-platform] 新增北向查询应用列表测试用例
Jul 16, 2025
fecfaed
[app-platform] 检视意见修改
Jul 16, 2025
27e5a53
[app-platform] 修改北向接口前缀
Jul 16, 2025
6a8db0c
[app-platform] 修改http请求过滤器匹配前缀
Jul 16, 2025
96dd0d7
[app-platform] 修改common目录下插件的pom文件,提取公共依赖插件
Jul 17, 2025
eb0a241
[app-platform] 移除apikey-auth非默认插件
Jul 17, 2025
5c30468
[app-platform] 检视意见修改
Jul 17, 2025
19df9aa
[app-platform] 检视意见修改
Jul 17, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
* This file is a part of the ModelEngine Project.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

package modelengine.fit.jober.aipp.northbound;

import modelengine.fit.jane.common.entity.OperationContext;
import modelengine.fit.jober.aipp.dto.aipplog.AippInstLogData;
import modelengine.fit.jober.aipp.dto.aipplog.AippInstLogDataDto;
import modelengine.fit.jober.aipp.genericable.adapter.AippLogServiceAdapter;
import modelengine.fit.jober.aipp.service.AippLogService;
import modelengine.fitframework.annotation.Component;

import java.util.List;

/**
* {@link AippLogServiceAdapter} 的适配器类的实现类。
*
* @author 陈潇文
* @since 2025-07-08
*/
@Component
public class AippLogServiceAdapterImpl implements AippLogServiceAdapter {
private final AippLogService aippLogService;

/**
* 用 aipp 实例历史记录服务接口的 {@link AippLogService} 构造 {@link AippLogServiceAdapterImpl}。
*
* @param aippLogService 表示 aipp 实例历史记录服务接口的 {@link AippLogService}。
*/
public AippLogServiceAdapterImpl(AippLogService aippLogService) {
this.aippLogService = aippLogService;
}

@Override
public List<AippInstLogData> queryChatRecentChatLog(String chatId, String appId, OperationContext context) {
List<AippInstLogDataDto> logDataDtoList = this.aippLogService.queryChatRecentChatLog(chatId, appId, context);
return logDataDtoList.stream()
.map(dto -> AippInstLogData.builder()
.aippId(dto.getAippId())
.version(dto.getVersion())
.instanceId(dto.getInstanceId())
.status(dto.getStatus())
.appName(dto.getAppName())
.appIcon(dto.getAppIcon())
.createAt(dto.getCreateAt())
.question(this.convertQuestion(dto.getQuestion()))
.instanceLogBodies(this.convertLogBodies(dto.getInstanceLogBodies()))
.build())
.toList();
}

private AippInstLogData.AippInstLogBody convertBody(AippInstLogDataDto.AippInstanceLogBody dtoBody) {
if (dtoBody == null) {
return null;
}
return AippInstLogData.AippInstLogBody.builder()
.logId(dtoBody.getLogId())
.logData(dtoBody.getLogData())
.logType(dtoBody.getLogType())
.createAt(dtoBody.getCreateAt())
.createUserAccount(dtoBody.getCreateUserAccount())
.build();
}

private AippInstLogData.AippInstLogBody convertQuestion(AippInstLogDataDto.AippInstanceLogBody question) {
if (question == null) {
return null;
}
return this.convertBody(question);
}

private List<AippInstLogData.AippInstLogBody> convertLogBodies(
List<AippInstLogDataDto.AippInstanceLogBody> logBodies) {
if (logBodies == null) {
return null;
}
return logBodies.stream().map(this::convertBody).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,25 @@
public class AppBuilderAppServiceAdapterImpl implements AppBuilderAppServiceAdapter {
private final AppBuilderAppService appBuilderAppService;

/**
* 用应用创建服务接口{@link AppBuilderAppService} 构造 {@link AppBuilderAppServiceAdapterImpl}。
*
* @param appBuilderAppService 表示应用创建服务接口的 {@link AppBuilderAppService}。
*/
public AppBuilderAppServiceAdapterImpl(AppBuilderAppService appBuilderAppService) {
this.appBuilderAppService = notNull(appBuilderAppService, "The app builder app service cannot be null.");
}

@Override
public RangedResultSet<AppMetadata> list(AppQueryParams params, OperationContext context) {
AppQueryCondition appQueryCondition = BeanUtils.copyProperties(params, AppQueryCondition.class);
AppQueryCondition appQueryCondition = this.convertParams(params);
if (params.getType() == null) {
params.setType("app");
}
appQueryCondition.setTenantId(context.getTenantId());
appQueryCondition.setType(params.getType());
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp = this.appBuilderAppService.list(appQueryCondition,
context, params.getOffset(), params.getLimit());
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp =
this.appBuilderAppService.list(appQueryCondition, context, params.getOffset(), params.getLimit());
return this.appMetadataDtoConvertToAdapter(rsp.getData());
}

Expand All @@ -55,4 +60,19 @@ RangedResultSet<AppMetadata> appMetadataDtoConvertToAdapter(RangedResultSet<AppB
.map(appBuilderAppMetadataDto -> BeanUtils.copyProperties(appBuilderAppMetadataDto, AppMetadata.class))
.collect(Collectors.toList()), dto.getRange());
}

private AppQueryCondition convertParams(AppQueryParams params) {
if (params == null) {
return null;
}
return AppQueryCondition.builder()
.ids(params.getIds())
.name(params.getName())
.state(params.getState())
.excludeNames(params.getExcludeNames())
.offset(Long.valueOf(params.getOffset()))
.limit(params.getLimit())
.type(params.getType())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
import modelengine.fit.jober.aipp.dto.chat.CreateAppChatRequest;
import modelengine.fit.jober.aipp.genericable.adapter.AppChatServiceAdapter;
import modelengine.fit.jober.aipp.service.AppChatService;

import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fit;
import modelengine.fitframework.flowable.Choir;
import modelengine.fitframework.serialization.ObjectSerializer;

import java.util.Map;

Expand All @@ -30,17 +27,19 @@
@Component
public class AppChatServiceAdapterImpl implements AppChatServiceAdapter {
private final AppChatService appChatService;
private final ObjectSerializer serializer;

public AppChatServiceAdapterImpl(AppChatService appChatService, @Fit(alias = "json") ObjectSerializer serializer) {
/**
* 用历史会话服务接口 {@link AppChatService} 构造 {@link AppChatServiceAdapterImpl}。
*
* @param appChatService 表示历史会话服务接口的 {@link AppChatService}。
*/
public AppChatServiceAdapterImpl(AppChatService appChatService) {
this.appChatService = notNull(appChatService, "The app chat service must not be null.");
this.serializer = notNull(serializer, "The serializer must not be null.");
}

@Override
public Choir<Object> chat(String appId, ChatRequest params, OperationContext operationContext, boolean isDebug) {
CreateAppChatRequest createAppChatRequest =
this.serializer.deserialize(this.serializer.serialize(params), CreateAppChatRequest.class);
CreateAppChatRequest createAppChatRequest = this.convertToCreateAppChatRequest(params);
createAppChatRequest.setAppId(appId);
return this.appChatService.chat(createAppChatRequest, operationContext, isDebug);
}
Expand All @@ -50,4 +49,27 @@ public Choir<Object> restartChat(String currentInstanceId, Map<String, Object> a
OperationContext operationContext) {
return this.appChatService.restartChat(currentInstanceId, additionalContext, operationContext);
}

private CreateAppChatRequest convertToCreateAppChatRequest(ChatRequest params) {
if (params == null) {
return null;
}
ChatRequest.Context ctx = params.getContext();
CreateAppChatRequest.Context newCtx = null;
if (ctx != null) {
newCtx = CreateAppChatRequest.Context.builder()
.useMemory(ctx.getUseMemory())
.userContext(ctx.getUserContext())
.atAppId(ctx.getAtAppId())
.atChatId(ctx.getAtChatId())
.dimension(ctx.getDimension())
.dimensionId(ctx.getDimensionId())
.build();
}
return CreateAppChatRequest.builder()
.chatId(params.getChatId())
.question(params.getQuestion())
.context(newCtx)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@
package modelengine.fit.jober.aipp.northbound;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import modelengine.fit.jane.common.entity.OperationContext;
import modelengine.fit.jane.common.response.Rsp;
import modelengine.fit.jober.aipp.condition.AppQueryCondition;
import modelengine.fit.jober.aipp.dto.AppBuilderAppMetadataDto;
import modelengine.fit.jober.aipp.dto.chat.AppMetadata;
import modelengine.fit.jober.aipp.dto.chat.AppQueryParams;
import modelengine.fit.jober.aipp.service.AppBuilderAppService;
import modelengine.fit.jober.common.RangeResult;
import modelengine.fit.jober.common.RangedResultSet;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* {@link AippChatServiceAdapterImpl} 的单元测试。
Expand Down Expand Up @@ -60,4 +68,31 @@ void testDtoConvertToAdapter() {
.containsExactly("testName1", "testName2");
assertThat(result.getResults()).extracting(AppMetadata::getType).containsExactly("testType1", "testType2");
}

@Test
@DisplayName("测试查询应用列表")
void shouldOkWhenTestQueryAppList() {
AppQueryParams params = AppQueryParams.builder()
.ids(Arrays.asList("id1", "id2"))
.excludeNames(Arrays.asList("name1", "name2"))
.name("name")
.state("active")
.offset(100)
.limit(20)
.type("app")
.build();
OperationContext operationContext = new OperationContext();
operationContext.setTenantId("tenantId");
List<AppBuilderAppMetadataDto> metaDtoList = new ArrayList<>();
metaDtoList.add(AppBuilderAppMetadataDto.builder().name("name1").build());
Rsp<RangedResultSet<AppBuilderAppMetadataDto>> rsp =
Rsp.ok(RangedResultSet.create(metaDtoList, params.getOffset(), params.getLimit(), metaDtoList.size()));
when(this.appBuilderAppService.list(any(AppQueryCondition.class),
any(OperationContext.class),
anyLong(),
anyInt())).thenReturn(rsp);
RangedResultSet<AppMetadata> resultSet = this.appBuilderAppServiceAdapterImpl.list(params, operationContext);
assertThat(resultSet.getResults().size()).isEqualTo(1);
assertThat(resultSet.getResults().get(0).getName()).isEqualTo("name1");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
* This file is a part of the ModelEngine Project.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

package modelengine.fit.jober.aipp.northbound;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import modelengine.fit.jane.common.entity.OperationContext;
import modelengine.fit.jober.aipp.dto.chat.ChatRequest;
import modelengine.fit.jober.aipp.dto.chat.CreateAppChatRequest;
import modelengine.fit.jober.aipp.service.AppChatService;
import modelengine.fitframework.flowable.Choir;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

/**
* {@link AppChatServiceAdapterImpl} 的单元测试。
*
* @author 陈潇文
* @since 2025-07-15
*/
public class AppChatServiceAdapterImplTest {
private final AppChatService appChatService = mock(AppChatService.class);
private final AppChatServiceAdapterImpl appChatServiceAdapter =
new AppChatServiceAdapterImpl(appChatService);

@Test
@DisplayName("测试对话")
void shouldOkWhenTestChat() {
String appId = "appId";
ChatRequest params = ChatRequest.builder().chatId("chatId").question("q").build();
Map<String, Object> userContext = new HashMap<>();
userContext.put("a", "aaa");
ChatRequest.Context context = ChatRequest.Context.builder()
.atChatId("atChatId")
.atAppId("atAppId")
.useMemory(true)
.dimension("dimension")
.dimensionId("dimensionId")
.userContext(userContext)
.build();
params.setContext(context);
OperationContext operationContext = new OperationContext();
boolean isDebug = true;
when(this.appChatService.chat(any(CreateAppChatRequest.class),
any(OperationContext.class),
anyBoolean())).thenReturn(mock(Choir.class));
// when
Choir<Object> objectChoir = Assertions.assertDoesNotThrow(() -> this.appChatServiceAdapter.chat(appId,
params,
operationContext,
isDebug));
// then
Assertions.assertNotNull(objectChoir);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
* This file is a part of the ModelEngine Project.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

package modelengine.fit.jober.aipp.dto.aipplog;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

/**
* aipp 实例历史记录数据。
*
* @author 陈潇文
* @since 2025-07-16
*/
@AllArgsConstructor
@Data
@Builder
@NoArgsConstructor
public class AippInstLogData {
private String aippId;
private String version;
private String instanceId;
private String status;
private String appName;
private String appIcon;
private LocalDateTime createAt;
private AippInstLogBody question;
private List<AippInstLogBody> instanceLogBodies;

/**
* 转换实例日志为实例日志体。
*/
@AllArgsConstructor
@Data
@Builder
@NoArgsConstructor
public static class AippInstLogBody {
private long logId;
private String logData;
private String logType;
private LocalDateTime createAt;
private String createUserAccount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
@NoArgsConstructor
@AllArgsConstructor
public class AppQueryParams {
@RequestQuery(name = "appIds", required = false)
@RequestQuery(name = "ids", required = false)
@Property(description = "查询的id列表")
private List<String> appIds;
private List<String> ids;

@RequestQuery(name = "name", required = false)
@Property(description = "查询的名字")
Expand Down
Loading