Skip to content

Commit 7b5180a

Browse files
authored
Merge pull request #37 from spring-ai-alibaba/feature/support_search_ext_params
feat(SearchProvider): 添加扩展参数支持机制
2 parents 9685ca2 + 0e9bc96 commit 7b5180a

File tree

3 files changed

+206
-5
lines changed

3 files changed

+206
-5
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2024-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.assistant.agent.extension.search.spi;
17+
18+
/**
19+
* SearchProvider 的扩展参数描述。
20+
*
21+
* <p>SearchProvider 实现类可以通过 {@link SearchProvider#getExtendedParameters()} 声明额外的工具参数,
22+
* 框架会自动将这些参数注册到 Tool 的 inputSchema / ParameterTree 中,
23+
* 调用时传入的值会被放入 {@link com.alibaba.assistant.agent.extension.search.model.SearchRequest#getFilters()} 中。
24+
*
25+
* @author Assistant Agent Team
26+
* @since 1.0.0
27+
*/
28+
public class SearchExtendedParameter {
29+
30+
/**
31+
* 参数名称(对应 JSON Schema property name,同时也是 filters 中的 key)
32+
*/
33+
private final String name;
34+
35+
/**
36+
* JSON Schema 类型,如 "string", "integer", "boolean" 等
37+
*/
38+
private final String type;
39+
40+
/**
41+
* 参数描述
42+
*/
43+
private final String description;
44+
45+
/**
46+
* 是否必填
47+
*/
48+
private final boolean required;
49+
50+
/**
51+
* 默认值,可为 null
52+
*/
53+
private final Object defaultValue;
54+
55+
private SearchExtendedParameter(Builder builder) {
56+
this.name = builder.name;
57+
this.type = builder.type;
58+
this.description = builder.description;
59+
this.required = builder.required;
60+
this.defaultValue = builder.defaultValue;
61+
}
62+
63+
public String getName() {
64+
return name;
65+
}
66+
67+
public String getType() {
68+
return type;
69+
}
70+
71+
public String getDescription() {
72+
return description;
73+
}
74+
75+
public boolean isRequired() {
76+
return required;
77+
}
78+
79+
public Object getDefaultValue() {
80+
return defaultValue;
81+
}
82+
83+
public static Builder builder() {
84+
return new Builder();
85+
}
86+
87+
public static class Builder {
88+
89+
private String name;
90+
91+
private String type = "string";
92+
93+
private String description = "";
94+
95+
private boolean required = false;
96+
97+
private Object defaultValue;
98+
99+
public Builder name(String name) {
100+
this.name = name;
101+
return this;
102+
}
103+
104+
public Builder type(String type) {
105+
this.type = type;
106+
return this;
107+
}
108+
109+
public Builder description(String description) {
110+
this.description = description;
111+
return this;
112+
}
113+
114+
public Builder required(boolean required) {
115+
this.required = required;
116+
return this;
117+
}
118+
119+
public Builder defaultValue(Object defaultValue) {
120+
this.defaultValue = defaultValue;
121+
return this;
122+
}
123+
124+
public SearchExtendedParameter build() {
125+
if (name == null || name.isEmpty()) {
126+
throw new IllegalArgumentException("SearchExtendedParameter name must not be empty");
127+
}
128+
return new SearchExtendedParameter(this);
129+
}
130+
131+
}
132+
133+
}
134+

assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/spi/SearchProvider.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.alibaba.assistant.agent.extension.search.model.SearchResultItem;
2020
import com.alibaba.assistant.agent.extension.search.model.SearchSourceType;
2121

22+
import java.util.Collections;
2223
import java.util.List;
2324

2425
/**
@@ -52,5 +53,19 @@ public interface SearchProvider {
5253
default String getName() {
5354
return this.getClass().getSimpleName();
5455
}
56+
57+
/**
58+
* 获取该Provider声明的扩展参数列表。
59+
*
60+
* <p>框架会将这些参数动态注册到搜索工具的 inputSchema / ParameterTree 中,
61+
* 调用时传入的值会被放入 {@link SearchRequest#getFilters()} 供 Provider 在 search 中读取。
62+
*
63+
* <p>默认返回空列表,即不声明任何扩展参数。
64+
*
65+
* @return 扩展参数列表
66+
*/
67+
default List<SearchExtendedParameter> getExtendedParameters() {
68+
return Collections.emptyList();
69+
}
5570
}
5671

assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/BaseSearchCodeactTool.java

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.alibaba.assistant.agent.extension.search.model.SearchResultItem;
3030
import com.alibaba.assistant.agent.extension.search.model.SearchResultSet;
3131
import com.alibaba.assistant.agent.extension.search.model.SearchSourceType;
32+
import com.alibaba.assistant.agent.extension.search.spi.SearchExtendedParameter;
3233
import com.alibaba.assistant.agent.extension.search.spi.SearchProvider;
3334
import com.fasterxml.jackson.annotation.JsonIgnore;
3435
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -165,7 +166,7 @@ private CodeactToolDefinition buildCodeactDefinition() {
165166
String inputSchema = toolDefinition.inputSchema();
166167

167168
// 构建 ParameterTree
168-
ParameterTree parameterTree = ParameterTree.builder()
169+
ParameterTree.Builder treeBuilder = ParameterTree.builder()
169170
.rawInputSchema(inputSchema)
170171
.addParameter(ParameterNode.builder()
171172
.name("query")
@@ -179,9 +180,29 @@ private CodeactToolDefinition buildCodeactDefinition() {
179180
.description("返回结果数量限制")
180181
.required(false)
181182
.defaultValue(10)
182-
.build())
183-
.addRequiredName("query")
184-
.build();
183+
.build());
184+
185+
// 动态添加 Provider 声明的扩展参数
186+
List<SearchExtendedParameter> extParams = searchProvider.getExtendedParameters();
187+
if (extParams != null) {
188+
for (SearchExtendedParameter ext : extParams) {
189+
ParameterNode.Builder nodeBuilder = ParameterNode.builder()
190+
.name(ext.getName())
191+
.type(ParameterType.fromJsonSchemaType(ext.getType()))
192+
.description(ext.getDescription())
193+
.required(ext.isRequired());
194+
if (ext.getDefaultValue() != null) {
195+
nodeBuilder.defaultValue(ext.getDefaultValue());
196+
}
197+
treeBuilder.addParameter(nodeBuilder.build());
198+
if (ext.isRequired()) {
199+
treeBuilder.addRequiredName(ext.getName());
200+
}
201+
}
202+
}
203+
204+
treeBuilder.addRequiredName("query");
205+
ParameterTree parameterTree = treeBuilder.build();
185206

186207
return DefaultCodeactToolDefinition.builder()
187208
.name(toolName)
@@ -277,8 +298,28 @@ private String buildInputSchema() {
277298
limitProp.put("default", 10);
278299
properties.put("limit", limitProp);
279300

301+
// 动态添加 Provider 声明的扩展参数
302+
List<String> requiredNames = new ArrayList<>();
303+
requiredNames.add("query");
304+
305+
List<SearchExtendedParameter> extParams = searchProvider.getExtendedParameters();
306+
if (extParams != null) {
307+
for (SearchExtendedParameter ext : extParams) {
308+
Map<String, Object> extProp = new LinkedHashMap<>();
309+
extProp.put("type", ext.getType());
310+
extProp.put("description", ext.getDescription());
311+
if (ext.getDefaultValue() != null) {
312+
extProp.put("default", ext.getDefaultValue());
313+
}
314+
properties.put(ext.getName(), extProp);
315+
if (ext.isRequired()) {
316+
requiredNames.add(ext.getName());
317+
}
318+
}
319+
}
320+
280321
schema.put("properties", properties);
281-
schema.put("required", Arrays.asList("query"));
322+
schema.put("required", requiredNames);
282323

283324
try {
284325
return objectMapper.writeValueAsString(schema);
@@ -303,6 +344,17 @@ private SearchRequest buildSearchRequest(Map<String, Object> params) {
303344
request.getSourceTypes().add(sourceType);
304345
request.setTopK(limit);
305346

347+
// 将 Provider 声明的扩展参数值放入 filters
348+
List<SearchExtendedParameter> extParams = searchProvider.getExtendedParameters();
349+
if (extParams != null) {
350+
for (SearchExtendedParameter ext : extParams) {
351+
Object value = params.get(ext.getName());
352+
if (value != null) {
353+
request.getFilters().put(ext.getName(), value);
354+
}
355+
}
356+
}
357+
306358
return request;
307359
}
308360

0 commit comments

Comments
 (0)