Skip to content

Commit 9734b96

Browse files
committed
feat: update cpde
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
1 parent 7315aec commit 9734b96

File tree

7 files changed

+101
-36
lines changed

7 files changed

+101
-36
lines changed

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/service/SAAWebSearchService.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.springframework.ai.chat.client.advisor.RetrievalAugmentationAdvisor;
1414
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
1515
import org.springframework.ai.chat.prompt.PromptTemplate;
16+
import org.springframework.ai.rag.postretrieval.ranking.DocumentRanker;
1617
import org.springframework.ai.rag.preretrieval.query.expansion.QueryExpander;
1718
import org.springframework.ai.rag.preretrieval.query.transformation.QueryTransformer;
1819
import org.springframework.beans.factory.annotation.Qualifier;
@@ -44,9 +45,10 @@ public SAAWebSearchService(
4445
ChatClient.Builder chatClientBuilder,
4546
QueryTransformer queryTransformer,
4647
QueryExpander queryExpander,
47-
@Qualifier("queryArgumentPromptTemplate") PromptTemplate queryArgumentPromptTemplate,
4848
IQSSearchEngine searchEngine,
49-
DataClean dataCleaner
49+
DataClean dataCleaner,
50+
DocumentRanker documentRanker,
51+
@Qualifier("queryArgumentPromptTemplate") PromptTemplate queryArgumentPromptTemplate
5052
) {
5153

5254
this.queryTransformer = queryTransformer;
@@ -60,7 +62,7 @@ public SAAWebSearchService(
6062
this.chatClient = chatClientBuilder
6163
.defaultOptions(
6264
DashScopeChatOptions.builder()
63-
.withModel("deepseek-r1")
65+
.withModel("qwen-plus")
6466
.withIncrementalOutput(false)
6567
.build())
6668
.build();
@@ -72,6 +74,8 @@ public SAAWebSearchService(
7274
.searchEngine(searchEngine)
7375
.dataCleaner(dataCleaner)
7476
.maxResults(2)
77+
.enableRanker(true)
78+
.documentRanker(documentRanker)
7579
.build();
7680
}
7781

@@ -98,8 +102,9 @@ private RetrievalAugmentationAdvisor createRetrievalAugmentationAdvisor() {
98102
new CustomContextQueryAugmenter(
99103
queryArgumentPromptTemplate,
100104
null,
101-
true))
102-
.queryExpander(queryExpander).documentJoiner(new ConcatenationDocumentJoiner())
105+
true)
106+
).queryExpander(queryExpander)
107+
.documentJoiner(new ConcatenationDocumentJoiner())
103108
.build();
104109
}
105110

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/config/WeSearchConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public QueryTransformer queryTransformer(
4545
return RewriteQueryTransformer.builder()
4646
.chatClientBuilder(chatClient.mutate())
4747
.promptTemplate(transformerPromptTemplate)
48-
.targetSearchSystem("Web search")
48+
.targetSearchSystem("联网搜索")
4949
.build();
5050
}
5151

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/rag/WebSearchRetriever.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import com.alibaba.cloud.ai.application.websearch.core.IQSSearchEngine;
66
import com.alibaba.cloud.ai.application.websearch.data.DataClean;
77
import com.alibaba.cloud.ai.application.websearch.entity.GenericSearchResult;
8+
import org.jetbrains.annotations.NotNull;
89
import org.slf4j.Logger;
910
import org.slf4j.LoggerFactory;
1011

1112
import org.springframework.ai.document.Document;
1213
import org.springframework.ai.rag.Query;
14+
import org.springframework.ai.rag.postretrieval.ranking.DocumentRanker;
1315
import org.springframework.ai.rag.retrieval.search.DocumentRetriever;
1416
import org.springframework.lang.Nullable;
1517

@@ -28,13 +30,20 @@ public class WebSearchRetriever implements DocumentRetriever {
2830

2931
private final DataClean dataCleaner;
3032

33+
private final DocumentRanker documentRanker;
34+
35+
private final boolean enableRanker;
36+
3137
private WebSearchRetriever(Builder builder) {
3238

3339
this.searchEngine = builder.searchEngine;
3440
this.maxResults = builder.maxResults;
3541
this.dataCleaner = builder.dataCleaner;
42+
this.documentRanker = builder.documentRanker;
43+
this.enableRanker = builder.enableRanker;
3644
}
3745

46+
@NotNull
3847
@Override
3948
public List<Document> retrieve(
4049
@Nullable Query query
@@ -48,7 +57,33 @@ public List<Document> retrieve(
4857
logger.debug("cleaner data: {}", cleanerData);
4958

5059
// 返回结果
51-
return dataCleaner.limitResults(cleanerData, maxResults);
60+
List<Document> documents = dataCleaner.limitResults(cleanerData, maxResults);
61+
62+
logger.debug("WebSearchRetriever#retrieve() document size: {}, raw documents: {}",
63+
documents.size(),
64+
documents.stream().map(Document::getId).toArray()
65+
);
66+
67+
return enableRanker ? ranking(query, documents) : documents;
68+
}
69+
70+
private List<Document> ranking(Query query, List<Document> documents) {
71+
72+
if (documents.size() == 1) {
73+
// 只有一个时,不需要 rank
74+
return documents;
75+
}
76+
77+
try {
78+
79+
List<Document> rankedDocuments = documentRanker.rank(query, documents);
80+
logger.debug("WebSearchRetriever#ranking() Ranked documents: {}", rankedDocuments.stream().map(Document::getId).toArray());
81+
return rankedDocuments;
82+
} catch (Exception e) {
83+
// 降级返回原始结果
84+
logger.error("ranking error", e);
85+
return documents;
86+
}
5287
}
5388

5489
public static WebSearchRetriever.Builder builder() {
@@ -64,6 +99,11 @@ public static final class Builder {
6499

65100
private DataClean dataCleaner;
66101

102+
private DocumentRanker documentRanker;
103+
104+
// 默认开启 ranking
105+
private Boolean enableRanker = true;
106+
67107
public WebSearchRetriever.Builder searchEngine(IQSSearchEngine searchEngine) {
68108

69109
this.searchEngine = searchEngine;
@@ -82,6 +122,16 @@ public WebSearchRetriever.Builder maxResults(int maxResults) {
82122
return this;
83123
}
84124

125+
public WebSearchRetriever.Builder documentRanker(DocumentRanker documentRanker) {
126+
this.documentRanker = documentRanker;
127+
return this;
128+
}
129+
130+
public WebSearchRetriever.Builder enableRanker(Boolean enableRanker) {
131+
this.enableRanker = enableRanker;
132+
return this;
133+
}
134+
85135
public WebSearchRetriever build() {
86136

87137
return new WebSearchRetriever(this);

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/rag/postretrieval/DashScopeDocumentRanker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public List<Document> rank(
7171
.filter(doc ->
7272
{
7373
// debug rerank output.
74-
logger.debug("doc id: {}, outputDocs id: {}", doc.getId(), outputDocs.getId());
74+
logger.debug("DashScopeDocumentRanker#rank() doc id: {}, outputDocs id: {}", doc.getId(), outputDocs.getId());
7575
return Objects.equals(doc.getId(), outputDocs.getId());
7676
})
7777
.findFirst();

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/rag/preretrieval/query/expansion/MultiQueryExpander.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public List<Query> expand(@Nullable Query query) {
8888
.call()
8989
.content();
9090

91+
logger.debug("MultiQueryExpander#expand() Response from chat client: {}", resp);
92+
9193
if (Objects.isNull(resp)) {
9294

9395
logger.warn("No response from chat client for query: {}. is return.", query.text());

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/rag/prompt/CustomContextQueryAugmenter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public CustomContextQueryAugmenter(
6969
this.emptyPromptTemplate = emptyPromptTemplate != null ? emptyPromptTemplate : DEFAULT_EMPTY_PROMPT_TEMPLATE;
7070
this.allowEmptyContext = allowEmptyContext != null ? allowEmptyContext : DEFAULT_ALLOW_EMPTY_PROMPT;
7171

72+
logger.debug("CustomContextQueryAugmenter promptTemplate: {}", promptTemplate.getTemplate());
73+
logger.debug("CustomContextQueryAugmenter emptyPromptTemplate: {}", emptyPromptTemplate);
74+
logger.debug("CustomContextQueryAugmenter allowEmptyContext: {}", allowEmptyContext);
75+
7276
PromptAssert.templateHasRequiredPlaceholders(this.promptTemplate, "query", "context");
7377
}
7478

spring-ai-alibaba-integration-example/backend/src/main/java/com/alibaba/cloud/ai/application/websearch/rag/prompt/PromptTemplateConfig.java

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@ public PromptTemplate transformerPromptTemplate() {
1717

1818
return new PromptTemplate(
1919
"""
20-
Given a user query, rewrite it to provide better results when querying a {target}.
21-
Remove any irrelevant information, and ensure the query is concise and specific.
20+
给定一个用户查询,重写用户问题,使得在 {target} 查询时提供更好的结果。
2221
23-
The output must be consistent with the user query's language.
22+
你应该遵循以下规则:
2423
25-
Original query:
24+
1. 删除任何不相关的信息,并确保查询简洁具体;
25+
2. 输出必须与用户查询的语言一致;
26+
3. 保证在大模型的角度更好理解与做出回答。
27+
28+
原始查询:
2629
{query}
2730
28-
Rewritten query:
31+
重写之后的查询:
2932
"""
3033
);
3134
}
@@ -36,38 +39,39 @@ public PromptTemplate queryArgumentPromptTemplate() {
3639

3740
return new PromptTemplate(
3841
"""
39-
You will be given a set of related document contexts to the question.
40-
Each document starts with a reference number like [[x]], where x is a number that may be repeated.
41-
Document without reference will be marked as [[null]].
42-
Please use the context and cite the context at the end of each sentence if applicable.
43-
Context information is below.
42+
你将获得一组与问题相关的文档上下文。
43+
每个文档都以参考编号开头,如 [[x]],其中 x 是可以重复的数字。
44+
没有引用的文档将被标记为 [[null]]
45+
请使用上下文,并在每个句子的末尾引用上下文(如果适用)。
46+
上下文信息如下:
4447
4548
---------------------
4649
{context}
4750
---------------------
4851
49-
Given the context information and no prior knowledge, generate a structured response to the user's question.
52+
在给定上下文信息且没有先验知识的情况下,生成对用户问题的结构化响应。
5053
51-
Follow these rules:
54+
在你回答用户问题时,请遵循以下规则:
5255
53-
1. If the answer is not in the context, just say that you don't know.
54-
2. Do not give any information that is not related to the question, and do not repeat.
55-
3. Avoid statements like "Based on the context..." or "The provided information...".
56-
4. Your answer must be correct, accurate and written by an expert using an unbiased and professional tone.
57-
5. The appropriate structure is automatically determined based on the characteristics of the content, but be sure to include subheadings to enhance readability.
58-
6. When generating a response, provide a clear conclusion or main idea first, and do not need to carry a title.
59-
7. Make sure each section has clear subheadings so the reader can better understand and follow the content.
60-
8. If the information is complex or has multiple sections, make sure each section has an appropriate title to create a hierarchical structure.
61-
9. Please cite the sentence or section with the reference numbers in the end, in the format [[x]].
62-
10. If a sentence or sections comes from multiple contexts, please list all applicable citations, like [[x]][[y]].
63-
11. You don`t have to cite if the reference is marked as [[null]].
64-
12. Other than code and specific names and citations, your answer must be written in the same language as the question.
65-
66-
Query: {query}
56+
1. 如果答案不在上下文中,就说你不知道;
57+
2. 不要提供任何与问题无关的信息,也不要输出任何的重复内容;
58+
3. 避免使用 “基于上下文...” 或 “The provided information...” 的说法;
59+
4. 你的答案必须正确、准确,并使用专家般公正和专业的语气撰写;
60+
5. 回答中适当的文本结构是根据内容的特点来确定的,请在输出中包含副标题以提高可读性;
61+
6. 生成回复时,先提供明确的结论或中心思想,不需要带有标题;
62+
7. 确保每个部分都有清晰的副标题,以便用户可以更好地理解和参考你的输出内容;
63+
8. 如果信息复杂或包含多个部分,请确保每个部分都有适当的标题以创建分层结构;
64+
9. 请以 [x] 格式引用末尾带有参考编号的句子或部分;
65+
10. 如果一个句子或章节来自多个上下文,请列出所有适用的引用,例如 [x][y];
66+
11. 你的输出答案必须保持美观且严谨的 markdown 格式。
67+
12. 因为你的输出保持 markdown 格式,请在引用上下文时,以超链接的形式带上参考文档中的链接,方便用户点击查看;
68+
13. 如果参考文献被标记为 [null],则不必引用;
69+
14. 除了代码。具体名称和引文外,你的答案必须用与问题相同的语言编写。
6770
68-
Answer:
71+
用户问题: {query}
72+
73+
你的回答:
6974
"""
7075
);
7176
}
72-
7377
}

0 commit comments

Comments
 (0)