Skip to content

Commit c1e28bb

Browse files
Msquittto陈潇文
andauthored
接入知识库功能优化 (#177)
* [app-platform] 优化知识库配置表单 * [app-platform] 增加QianfanRepoServiceImpl类测试用例 * [app-platform] 增加QianfanKnowledgeBaseManager类测试用例 * [app-platform] 检视意见修改 --------- Co-authored-by: 陈潇文 <chenxiaowen17@huawei.com>
1 parent dc11fb8 commit c1e28bb

File tree

10 files changed

+597
-2
lines changed

10 files changed

+597
-2
lines changed

app-knowledge/plugins/qianfan-knowledge/pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,30 @@
4040
<groupId>org.mapstruct</groupId>
4141
<artifactId>mapstruct-processor</artifactId>
4242
</dependency>
43+
44+
<!-- Jackson -->
4345
<dependency>
4446
<groupId>com.fasterxml.jackson.core</groupId>
4547
<artifactId>jackson-databind</artifactId>
4648
</dependency>
49+
50+
<!-- Test -->
51+
<dependency>
52+
<groupId>org.fitframework</groupId>
53+
<artifactId>fit-test-framework</artifactId>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.junit.jupiter</groupId>
57+
<artifactId>junit-jupiter</artifactId>
58+
</dependency>
59+
<dependency>
60+
<groupId>org.mockito</groupId>
61+
<artifactId>mockito-core</artifactId>
62+
</dependency>
63+
<dependency>
64+
<groupId>org.assertj</groupId>
65+
<artifactId>assertj-core</artifactId>
66+
</dependency>
4767
</dependencies>
4868

4969
<build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.jade.knowledge;
8+
9+
import static modelengine.fitframework.util.IoUtils.content;
10+
11+
import modelengine.fit.http.annotation.PostMapping;
12+
import modelengine.fit.http.annotation.RequestBody;
13+
import modelengine.fit.http.annotation.RequestMapping;
14+
import modelengine.fit.http.annotation.RequestQuery;
15+
import modelengine.fit.http.client.HttpClientException;
16+
import modelengine.fitframework.annotation.Component;
17+
import modelengine.fitframework.serialization.ObjectSerializer;
18+
import modelengine.jade.knowledge.entity.QianfanResponse;
19+
20+
import java.io.IOException;
21+
import java.util.Map;
22+
23+
/**
24+
* 表示千帆内部接口的打桩实现。
25+
*
26+
* @author 陈潇文
27+
* @since 2025-05-07
28+
*/
29+
@Component
30+
@RequestMapping(path = "/v2", group = "千帆知识库内部接口打桩")
31+
public class MockedQianfanKnowledgeBaseInnerController {
32+
private final ObjectSerializer serializer;
33+
34+
public MockedQianfanKnowledgeBaseInnerController(ObjectSerializer serializer) {
35+
this.serializer = serializer;
36+
}
37+
38+
@PostMapping(path = "/knowledgeBase")
39+
public Map<String, Object> listRepos(@RequestBody MockedQianfanKnowledgeListQueryParam param,
40+
@RequestQuery(name = "Action", defaultValue = "DescribeKnowledgeBases") String action) throws IOException {
41+
if (param.getKeyword().equals("error")) {
42+
throw new HttpClientException("error");
43+
}
44+
String resourceName = "/listRepoResult.json";
45+
String jsonContent = content(QianfanResponse.class, resourceName);
46+
return serializer.deserialize(jsonContent, Map.class);
47+
}
48+
49+
@PostMapping(path = "/knowledgebases/query")
50+
public Map<String, Object> listRepos(@RequestBody MockedQianfanRetrievalParam param) throws IOException {
51+
if (param.getQuery().equals("error")) {
52+
throw new HttpClientException("error");
53+
}
54+
String resourceName = "/retrieveResult.json";
55+
String jsonContent = content(QianfanResponse.class, resourceName);
56+
return serializer.deserialize(jsonContent, Map.class);
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
package modelengine.jade.knowledge;
8+
9+
import lombok.Data;
10+
import modelengine.fitframework.serialization.annotation.SerializeStrategy;
11+
import modelengine.jade.knowledge.dto.QianfanKnowledgeListQueryParam;
12+
13+
/**
14+
* 表示 {@link QianfanKnowledgeListQueryParam} 类的测试类实现。
15+
*
16+
* @author 陈潇文
17+
* @since 2025-05-08
18+
*/
19+
@Data
20+
@SerializeStrategy(include = SerializeStrategy.Include.NON_NULL)
21+
public class MockedQianfanKnowledgeListQueryParam {
22+
/**
23+
* 知识库查询的起始id。
24+
*/
25+
private String marker;
26+
27+
/**
28+
* 知识库查询的关键字。
29+
*/
30+
private String keyword;
31+
32+
/**
33+
* 查询的知识库数量上限。
34+
*/
35+
private Integer maxKeys;
36+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
package modelengine.jade.knowledge;
8+
9+
import lombok.Data;
10+
import modelengine.fitframework.annotation.Property;
11+
import modelengine.fitframework.serialization.annotation.SerializeStrategy;
12+
import modelengine.jade.knowledge.dto.QianfanPipelineConfigQueryParam;
13+
import modelengine.jade.knowledge.dto.QianfanRetrievalParam;
14+
15+
import java.util.List;
16+
17+
/**
18+
* 表示 {@link QianfanRetrievalParam} 类的测试类实现。
19+
*
20+
* @author 陈潇文
21+
* @since 2025-05-08
22+
*/
23+
@Data
24+
@SerializeStrategy(include = SerializeStrategy.Include.NON_NULL)
25+
public class MockedQianfanRetrievalParam {
26+
/**
27+
* 返回前多少的条目。
28+
*/
29+
private int top;
30+
/**
31+
* 检索策略。
32+
*/
33+
private String type;
34+
/**
35+
* 检索query。
36+
*/
37+
private String query;
38+
/**
39+
* 指定知识库的id集合。
40+
*/
41+
@Property(description = "knowledgebase_ids", name = "knowledgebase_ids")
42+
private List<String> knowledgebaseIds;
43+
/**
44+
* 检索配置。
45+
*/
46+
@Property(description = "pipeline_config", name = "pipeline_config")
47+
private QianfanPipelineConfigQueryParam pipelineConfig;
48+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.jade.knowledge;
8+
9+
import modelengine.fit.http.client.HttpClassicClientResponse;
10+
import modelengine.fitframework.annotation.Fit;
11+
import modelengine.fitframework.test.annotation.MvcTest;
12+
import modelengine.fitframework.test.domain.mvc.MockMvc;
13+
import modelengine.jade.knowledge.dto.QianfanKnowledgeListQueryParam;
14+
import modelengine.jade.knowledge.dto.QianfanRetrievalParam;
15+
import modelengine.jade.knowledge.entity.QianfanKnowledgeEntity;
16+
import modelengine.jade.knowledge.entity.QianfanKnowledgeListEntity;
17+
import modelengine.jade.knowledge.entity.QianfanRetrievalChunksEntity;
18+
import modelengine.jade.knowledge.entity.QianfanRetrievalResult;
19+
import modelengine.jade.knowledge.exception.KnowledgeException;
20+
import modelengine.jade.knowledge.external.QianfanKnowledgeBaseManager;
21+
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.DisplayName;
25+
import org.junit.jupiter.api.Test;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
29+
30+
import java.io.IOException;
31+
import java.lang.reflect.Field;
32+
import java.util.HashMap;
33+
import java.util.Map;
34+
35+
/**
36+
* 表示 {@link QianfanKnowledgeBaseManager} 的测试集。
37+
*
38+
* @author 陈潇文
39+
* @since 2025-05-06
40+
*/
41+
@MvcTest(classes = {MockedQianfanKnowledgeBaseInnerController.class, QianfanKnowledgeBaseManager.class})
42+
public class QianfanKnowledgeBaseManagerTest {
43+
private String apiKey = "123";
44+
45+
@Fit
46+
QianfanKnowledgeBaseManager manager;
47+
48+
@Fit
49+
private MockMvc mockMvc;
50+
51+
private HttpClassicClientResponse<?> response;
52+
53+
@BeforeEach
54+
void setUp() throws Exception {
55+
Field qianfanUrls = manager.getClass().getDeclaredField("qianfanUrls");
56+
qianfanUrls.setAccessible(true);
57+
Map<String, String> urls = new HashMap<>();
58+
urls.put("knowledgeList",
59+
"http://localhost:" + mockMvc.getPort() + "/v2/knowledgeBase?Action=DescribeKnowledgeBases");
60+
urls.put("knowledgeRetrieve", "http://localhost:" + mockMvc.getPort() + "/v2/knowledgebases/query");
61+
qianfanUrls.set(manager, urls);
62+
}
63+
64+
@AfterEach
65+
void teardown() throws IOException {
66+
if (this.response != null) {
67+
this.response.close();
68+
}
69+
}
70+
71+
@Test
72+
@DisplayName("查询知识库列表成功")
73+
public void shouldOkWhenListRepo() {
74+
QianfanKnowledgeListQueryParam param = QianfanKnowledgeListQueryParam.builder().keyword("ok").build();
75+
QianfanKnowledgeListEntity entity = this.manager.listRepos(apiKey, param);
76+
assertThat(entity.getData().size()).isEqualTo(2);
77+
assertThat(entity.getData().get(0)).extracting(QianfanKnowledgeEntity::getId,
78+
QianfanKnowledgeEntity::getName,
79+
QianfanKnowledgeEntity::getDescription).containsExactly("1", "test1", "test1知识库");
80+
assertThat(entity.getData().get(1)).extracting(QianfanKnowledgeEntity::getId,
81+
QianfanKnowledgeEntity::getName,
82+
QianfanKnowledgeEntity::getDescription).containsExactly("2", "test2", "test2知识库");
83+
}
84+
85+
@Test
86+
@DisplayName("查询知识库列表失败,抛出异常")
87+
public void shouldFailWhenListRepoThrowException() {
88+
QianfanKnowledgeListQueryParam param = QianfanKnowledgeListQueryParam.builder().keyword("error").build();
89+
assertThatThrownBy(() -> this.manager.listRepos(apiKey, param)).isInstanceOf(KnowledgeException.class)
90+
.extracting("code")
91+
.isEqualTo(130703005);
92+
}
93+
94+
@Test
95+
@DisplayName("检索知识库成功")
96+
public void shouldOkWhenRetrieve() {
97+
QianfanRetrievalParam param = QianfanRetrievalParam.builder().query("ok").build();
98+
QianfanRetrievalResult result = this.manager.retrieve(apiKey, param);
99+
assertThat(result.getTotalCount()).isEqualTo(3);
100+
assertThat(result.getChunks().get(0)).extracting(QianfanRetrievalChunksEntity::getChunkId,
101+
QianfanRetrievalChunksEntity::getContent,
102+
QianfanRetrievalChunksEntity::getDocumentId,
103+
QianfanRetrievalChunksEntity::getDocumentName,
104+
QianfanRetrievalChunksEntity::getKnowledgebaseId)
105+
.containsExactly("chunk1", "content1", "doc1", "doc1.txt", "know1");
106+
}
107+
108+
@Test
109+
@DisplayName("检索知识库失败,抛出异常")
110+
public void shouldFailWhenRetrieveThrowException() {
111+
QianfanRetrievalParam param = QianfanRetrievalParam.builder().query("error").build();
112+
assertThatThrownBy(() -> this.manager.retrieve(apiKey, param)).isInstanceOf(KnowledgeException.class)
113+
.extracting("code")
114+
.isEqualTo(130703005);
115+
}
116+
}

0 commit comments

Comments
 (0)