Skip to content

Commit b297203

Browse files
Darlingxxx-ParanoidJiang Chen-Qinchen (BSH GDS-IY3B)
andauthored
feat: support ai-proxy configuration (spring-ai-alibaba#401)
* feat: support ai-proxy configuration for DynamicModelFactory * style: fix license header and code formatting * feat: support model-level network proxy configuration * style: fix license header and code formatting * style: fix code style --------- Co-authored-by: Jiang Chen-Qinchen (BSH GDS-IY3B) <jch3nj@bosch.com>
1 parent 1954cd4 commit b297203

File tree

9 files changed

+347
-132
lines changed

9 files changed

+347
-132
lines changed

data-agent-frontend/src/services/modelConfig.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export interface ModelConfig {
2929
isActive?: boolean;
3030
completionsPath?: string; // 对话模型路径
3131
embeddingsPath?: string; // 嵌入模型路径
32+
proxyEnabled?: boolean; //代理开关,默认为关闭(直连)
33+
proxyHost?: string;
34+
proxyPort?: number;
35+
proxyUsername?: string;
36+
proxyPassword?: string;
3237
}
3338

3439
export interface ModelCheckReady {

data-agent-frontend/src/views/ModelConfig.vue

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,52 @@
274274
</el-form-item>
275275
</el-form>
276276

277+
<el-divider content-position="left">网络代理配置</el-divider>
278+
279+
<el-form-item label="启用代理">
280+
<el-switch v-model="formData.proxyEnabled" />
281+
<span class="form-tip" style="margin-left: 10px">
282+
如果您的服务器处于受限内网,请开启代理以连接 AI 服务
283+
</span>
284+
</el-form-item>
285+
286+
<transition name="el-fade-in">
287+
<div v-if="formData.proxyEnabled">
288+
<el-form-item label="代理主机" prop="proxyHost" :required="formData.proxyEnabled">
289+
<el-input
290+
v-model="formData.proxyHost"
291+
placeholder="例如: 127.0.0.1 或 proxy.example.com"
292+
/>
293+
</el-form-item>
294+
295+
<el-form-item label="代理端口" prop="proxyPort" :required="formData.proxyEnabled">
296+
<el-input-number
297+
v-model="formData.proxyPort"
298+
:min="1"
299+
:max="65535"
300+
controls-position="right"
301+
style="width: 100%"
302+
/>
303+
</el-form-item>
304+
305+
<el-form-item label="代理用户名" prop="proxyUsername">
306+
<el-input
307+
v-model="formData.proxyUsername"
308+
placeholder="可选,代理服务器需要认证时填写"
309+
/>
310+
</el-form-item>
311+
312+
<el-form-item label="代理密码" prop="proxyPassword">
313+
<el-input
314+
v-model="formData.proxyPassword"
315+
type="password"
316+
show-password
317+
placeholder="可选"
318+
/>
319+
</el-form-item>
320+
</div>
321+
</transition>
322+
277323
<template #footer>
278324
<span class="dialog-footer">
279325
<el-button @click="dialogVisible = false">取消</el-button>
@@ -323,6 +369,11 @@
323369
completionsPath: '',
324370
embeddingsPath: '',
325371
isActive: false,
372+
proxyEnabled: false,
373+
proxyHost: '',
374+
proxyPort: 7890, // 给个常用的默认端口
375+
proxyUsername: '',
376+
proxyPassword: '',
326377
});
327378
328379
// 提供商与API地址的映射
@@ -373,6 +424,30 @@
373424
trigger: 'blur',
374425
},
375426
],
427+
proxyHost: [
428+
{
429+
validator: (_rule, value, callback) => {
430+
if (formData.value.proxyEnabled && (!value || value.trim() === '')) {
431+
callback(new Error('启用代理时,必须填写代理主机地址'));
432+
} else {
433+
callback();
434+
}
435+
},
436+
trigger: 'blur',
437+
},
438+
],
439+
proxyPort: [
440+
{
441+
validator: (_rule, value, callback) => {
442+
if (formData.value.proxyEnabled && !value) {
443+
callback(new Error('启用代理时,必须填写代理端口'));
444+
} else {
445+
callback();
446+
}
447+
},
448+
trigger: 'blur',
449+
},
450+
],
376451
};
377452
378453
// 计算属性

data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/converter/ModelConfigConverter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public static ModelConfigDTO toDTO(ModelConfig entity) {
4343
.modelType(entity.getModelType().getCode())
4444
.completionsPath(entity.getCompletionsPath())
4545
.embeddingsPath(entity.getEmbeddingsPath())
46+
.proxyEnabled(entity.getProxyEnabled())
47+
.proxyHost(entity.getProxyHost())
48+
.proxyPort(entity.getProxyPort())
49+
.proxyUsername(entity.getProxyUsername())
50+
.proxyPassword(entity.getProxyPassword())
4651
.build();
4752
}
4853

@@ -64,6 +69,11 @@ public static ModelConfig toEntity(ModelConfigDTO dto) {
6469
entity.setModelType(ModelType.fromCode(dto.getModelType()));
6570
entity.setCompletionsPath(dto.getCompletionsPath());
6671
entity.setEmbeddingsPath(dto.getEmbeddingsPath());
72+
entity.setProxyEnabled(dto.getProxyEnabled());
73+
entity.setProxyHost(dto.getProxyHost());
74+
entity.setProxyPort(dto.getProxyPort());
75+
entity.setProxyUsername(dto.getProxyUsername());
76+
entity.setProxyPassword(dto.getProxyPassword());
6777
// 默认值处理
6878
entity.setIsActive(false);
6979
entity.setIsDeleted(0);

data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/dto/ModelConfigDTO.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,15 @@ public class ModelConfigDTO {
5858

5959
private Boolean isActive = true;
6060

61+
// 模型代理配置,默认关闭(使用直连)
62+
private Boolean proxyEnabled = false;
63+
64+
private String proxyHost;
65+
66+
private Integer proxyPort;
67+
68+
private String proxyUsername;
69+
70+
private String proxyPassword;
71+
6172
}

data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/entity/ModelConfig.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,15 @@ public class ModelConfig {
5959
// 0=未删除, 1=已删除
6060
private Integer isDeleted;
6161

62+
// ai-proxy设置(默认关闭,使用直连)
63+
private Boolean proxyEnabled;
64+
65+
private String proxyHost;
66+
67+
private Integer proxyPort;
68+
69+
private String proxyUsername;
70+
71+
private String proxyPassword;
72+
6273
}
Lines changed: 129 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,129 @@
1-
/*
2-
* Copyright 2024-2026 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.cloud.ai.dataagent.mapper;
17-
18-
import com.alibaba.cloud.ai.dataagent.entity.ModelConfig;
19-
import org.apache.ibatis.annotations.*;
20-
21-
import java.util.List;
22-
23-
@Mapper
24-
public interface ModelConfigMapper {
25-
26-
@Select("""
27-
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens, model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted FROM model_config WHERE is_deleted = 0 ORDER BY created_time DESC
28-
""")
29-
List<ModelConfig> findAll();
30-
31-
@Select("""
32-
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens, model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted FROM model_config WHERE id = #{id} AND is_deleted = 0
33-
""")
34-
ModelConfig findById(Integer id);
35-
36-
@Select("SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens, model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted FROM model_config WHERE model_type = #{modelType} AND is_active = 1 AND is_deleted = 0 LIMIT 1")
37-
ModelConfig selectActiveByType(@Param("modelType") String modelType);
38-
39-
@Update("UPDATE model_config SET is_active = 0 WHERE model_type = #{modelType} AND id != #{currentId} AND is_deleted = 0")
40-
void deactivateOthers(@Param("modelType") String modelType, @Param("currentId") Integer currentId);
41-
42-
@Select("""
43-
<script>
44-
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens, model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted FROM model_config
45-
<where>
46-
is_deleted = 0
47-
<if test='provider != null and provider != ""'>
48-
AND provider = #{provider}
49-
</if>
50-
<if test='keyword != null and keyword != ""'>
51-
AND (provider LIKE CONCAT('%', #{keyword}, '%')
52-
OR base_url LIKE CONCAT('%', #{keyword}, '%')
53-
OR model_name LIKE CONCAT('%', #{keyword}, '%'))
54-
</if>
55-
<if test='isActive != null'>
56-
AND is_active = #{isActive}
57-
</if>
58-
<if test='maxTokens != null'>
59-
AND max_tokens = #{maxTokens}
60-
</if>
61-
<if test='modelType != null'>
62-
AND model_type = #{modelType}
63-
</if>
64-
</where>
65-
ORDER BY created_time DESC
66-
</script>
67-
""")
68-
List<ModelConfig> findByConditions(@Param("provider") String provider, @Param("keyword") String keyword,
69-
@Param("isActive") Boolean isActive, @Param("maxTokens") Integer maxTokens,
70-
@Param("modelType") String modelType);
71-
72-
@Insert("""
73-
INSERT INTO model_config (provider, base_url, api_key, model_name, temperature, is_active, max_tokens, model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted)
74-
VALUES (#{provider}, #{baseUrl}, #{apiKey}, #{modelName}, #{temperature}, #{isActive}, #{maxTokens}, #{modelType}, #{completionsPath}, #{embeddingsPath}, NOW(), NOW(), 0)
75-
""")
76-
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
77-
int insert(ModelConfig modelConfig);
78-
79-
@Update("""
80-
<script>
81-
UPDATE model_config
82-
<trim prefix="SET" suffixOverrides=",">
83-
<if test='provider != null'>provider = #{provider},</if>
84-
<if test='baseUrl != null'>base_url = #{baseUrl},</if>
85-
<if test='apiKey != null'>api_key = #{apiKey},</if>
86-
<if test='modelName != null'>model_name = #{modelName},</if>
87-
<if test='temperature != null'>temperature = #{temperature},</if>
88-
<if test='isActive != null'>is_active = #{isActive},</if>
89-
<if test='maxTokens != null'>max_tokens = #{maxTokens},</if>
90-
<if test='modelType != null'>model_type = #{modelType},</if>
91-
<if test='completionsPath != null'>completions_path = #{completionsPath},</if>
92-
<if test='embeddingsPath != null'>embeddings_path = #{embeddingsPath},</if>
93-
<if test='isDeleted != null'>is_deleted = #{isDeleted},</if>
94-
updated_time = NOW()
95-
</trim>
96-
WHERE id = #{id}
97-
</script>
98-
""")
99-
int updateById(ModelConfig modelConfig);
100-
101-
@Update("""
102-
UPDATE model_config SET is_deleted = 1 WHERE id = #{id}
103-
""")
104-
int deleteById(Integer id);
105-
106-
}
1+
/*
2+
* Copyright 2024-2026 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.cloud.ai.dataagent.mapper;
17+
18+
import com.alibaba.cloud.ai.dataagent.entity.ModelConfig;
19+
import org.apache.ibatis.annotations.*;
20+
21+
import java.util.List;
22+
23+
@Mapper
24+
public interface ModelConfigMapper {
25+
26+
@Select("""
27+
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens,
28+
model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted,
29+
proxy_enabled, proxy_host, proxy_port, proxy_username, proxy_password
30+
FROM model_config WHERE is_deleted = 0 ORDER BY created_time DESC
31+
""")
32+
List<ModelConfig> findAll();
33+
34+
@Select("""
35+
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens,
36+
model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted,
37+
proxy_enabled, proxy_host, proxy_port, proxy_username, proxy_password
38+
FROM model_config WHERE id = #{id} AND is_deleted = 0
39+
""")
40+
ModelConfig findById(Integer id);
41+
42+
@Select("""
43+
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens,
44+
model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted,
45+
proxy_enabled, proxy_host, proxy_port, proxy_username, proxy_password
46+
FROM model_config WHERE model_type = #{modelType} AND is_active = 1 AND is_deleted = 0 LIMIT 1
47+
""")
48+
ModelConfig selectActiveByType(@Param("modelType") String modelType);
49+
50+
@Update("UPDATE model_config SET is_active = 0 WHERE model_type = #{modelType} AND id != #{currentId} AND is_deleted = 0")
51+
void deactivateOthers(@Param("modelType") String modelType, @Param("currentId") Integer currentId);
52+
53+
@Select("""
54+
<script>
55+
SELECT id, provider, base_url, api_key, model_name, temperature, is_active, max_tokens,
56+
model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted,
57+
proxy_enabled, proxy_host, proxy_port, proxy_username, proxy_password
58+
FROM model_config
59+
<where>
60+
is_deleted = 0
61+
<if test='provider != null and provider != ""'>
62+
AND provider = #{provider}
63+
</if>
64+
<if test='keyword != null and keyword != ""'>
65+
AND (provider LIKE CONCAT('%', #{keyword}, '%')
66+
OR base_url LIKE CONCAT('%', #{keyword}, '%')
67+
OR model_name LIKE CONCAT('%', #{keyword}, '%'))
68+
</if>
69+
<if test='isActive != null'>
70+
AND is_active = #{isActive}
71+
</if>
72+
<if test='maxTokens != null'>
73+
AND max_tokens = #{maxTokens}
74+
</if>
75+
<if test='modelType != null'>
76+
AND model_type = #{modelType}
77+
</if>
78+
</where>
79+
ORDER BY created_time DESC
80+
</script>
81+
""")
82+
List<ModelConfig> findByConditions(@Param("provider") String provider, @Param("keyword") String keyword,
83+
@Param("isActive") Boolean isActive, @Param("maxTokens") Integer maxTokens,
84+
@Param("modelType") String modelType);
85+
86+
@Insert("""
87+
INSERT INTO model_config (provider, base_url, api_key, model_name, temperature, is_active, max_tokens,
88+
model_type, completions_path, embeddings_path, created_time, updated_time, is_deleted,
89+
proxy_enabled, proxy_host, proxy_port, proxy_username, proxy_password)
90+
VALUES (#{provider}, #{baseUrl}, #{apiKey}, #{modelName}, #{temperature}, #{isActive}, #{maxTokens},
91+
#{modelType}, #{completionsPath}, #{embeddingsPath}, NOW(), NOW(), 0,
92+
#{proxyEnabled}, #{proxyHost}, #{proxyPort}, #{proxyUsername}, #{proxyPassword})
93+
""")
94+
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
95+
int insert(ModelConfig modelConfig);
96+
97+
@Update("""
98+
<script>
99+
UPDATE model_config
100+
<trim prefix="SET" suffixOverrides=",">
101+
<if test='provider != null'>provider = #{provider},</if>
102+
<if test='baseUrl != null'>base_url = #{baseUrl},</if>
103+
<if test='apiKey != null'>api_key = #{apiKey},</if>
104+
<if test='modelName != null'>model_name = #{modelName},</if>
105+
<if test='temperature != null'>temperature = #{temperature},</if>
106+
<if test='isActive != null'>is_active = #{isActive},</if>
107+
<if test='maxTokens != null'>max_tokens = #{maxTokens},</if>
108+
<if test='modelType != null'>model_type = #{modelType},</if>
109+
<if test='completionsPath != null'>completions_path = #{completionsPath},</if>
110+
<if test='embeddingsPath != null'>embeddings_path = #{embeddingsPath},</if>
111+
<if test='isDeleted != null'>is_deleted = #{isDeleted},</if>
112+
<if test='proxyEnabled != null'>proxy_enabled = #{proxyEnabled},</if>
113+
<if test='proxyHost != null'>proxy_host = #{proxyHost},</if>
114+
<if test='proxyPort != null'>proxy_port = #{proxyPort},</if>
115+
<if test='proxyUsername != null'>proxy_username = #{proxyUsername},</if>
116+
<if test='proxyPassword != null'>proxy_password = #{proxyPassword},</if>
117+
updated_time = NOW()
118+
</trim>
119+
WHERE id = #{id}
120+
</script>
121+
""")
122+
int updateById(ModelConfig modelConfig);
123+
124+
@Update("""
125+
UPDATE model_config SET is_deleted = 1 WHERE id = #{id}
126+
""")
127+
int deleteById(Integer id);
128+
129+
}

0 commit comments

Comments
 (0)