Skip to content

Commit 04fe8cf

Browse files
committed
fix: add s model download
1 parent 845f988 commit 04fe8cf

10 files changed

Lines changed: 595 additions & 8 deletions

File tree

example/s.yaml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
edition: 3.0.0
2+
name: ai-model-app
3+
access: quanxi
4+
5+
resources:
6+
modelDemo:
7+
component: fc3@dev
8+
props:
9+
region: cn-shanghai
10+
runtime: custom-container
11+
functionName: ${env('fc_component_function_name', 'ai-model-test-qwen')}
12+
description: model service from functionai test
13+
logConfig: auto
14+
vpcConfig: auto
15+
nasConfig: auto
16+
instanceConcurrency: 20
17+
cpu: 8
18+
memorySize: 65536
19+
diskSize: 10240
20+
timeout: 300
21+
gpuConfig:
22+
gpuMemorySize: 49152
23+
gpuType: fc.gpu.ada.1
24+
customContainerConfig:
25+
image: >-
26+
serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai/dms-vllm:openai_v0.10.0
27+
port: 9000
28+
entrypoint:
29+
- vllm
30+
- serve
31+
- /mnt/${env('fc_component_function_name', 'ai-model-test-qwen')}/${env('MODEL_ID', 'Qwen/Qwen3-32B-AWQ')}
32+
- --port
33+
- "9000"
34+
- --served-model-name
35+
- ${env('MODEL_ID', 'Qwen/Qwen3-32B-AWQ')}
36+
# - Qwen/Qwen3-14B
37+
- --tensor-parallel-size
38+
- "1"
39+
- --trust-remote-code # 添加这个参数
40+
- --max-model-len
41+
- "4096"
42+
triggers: # 默认,用户可能关注的是开启 authType 是 bear token
43+
- triggerConfig:
44+
methods:
45+
- GET
46+
- POST
47+
- PUT
48+
- DELETE
49+
authType: anonymous
50+
disableURLInternet: false
51+
triggerName: httpTrigger
52+
description: ''
53+
qualifier: LATEST
54+
triggerType: http
55+
provisionConfig:
56+
target: 1
57+
alwaysAllocateCPU: false
58+
alwaysAllocateGPU: false
59+
mode: sync
60+
61+
supplement:
62+
modelConfig:
63+
source: modelscope
64+
id: ${env('MODEL_ID', 'Qwen/Qwen3-32B-AWQ')}
65+
# id: Qwen/Qwen3-14B
66+
storage: nas
67+
role: acs:ram::${config('AccountID')}:role/aliyundevsdefaultrole
68+

example/test_models.sh

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/bash
2+
3+
# 定义日志文件
4+
LOG_FILE="test_models.log"
5+
6+
# 清空或创建日志文件
7+
> "$LOG_FILE"
8+
9+
# 日志记录函数
10+
log() {
11+
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
12+
}
13+
14+
# 定义model_id列表
15+
MODEL_IDS=("Qwen/Qwen2-Audio-7B-Instruct" "Qwen/Qwen2.5-0.5B-Instruct" "Qwen/Qwen3-32B-AWQ" "Qwen/Qwen3-14B" "Qwen/QwQ-32B-AWQ")
16+
17+
# 检查yaml文件是否存在
18+
YAML_FILE="s.yaml"
19+
if [ ! -f "$YAML_FILE" ]; then
20+
log "Error: $YAML_FILE not found!"
21+
exit 1
22+
fi
23+
24+
# 遍历每个model_id
25+
for MODEL_ID in "${MODEL_IDS[@]}"; do
26+
log "========================================"
27+
log "Testing model: $MODEL_ID"
28+
log "========================================"
29+
30+
# 生成随机函数名
31+
RANDOM_STRING=$(openssl rand -hex 16)
32+
export fc_component_function_name=ai-model-qwen-$RANDOM_STRING
33+
export NEW_MODEL_SERVICE_CLIENT_CONNECT_TIMEOUT=10000
34+
export MODEL_ID=$MODEL_ID
35+
36+
# 下载模型
37+
log "Downloading model..."
38+
DOWNLOAD_OUTPUT=$(s model download 2>&1)
39+
echo "$DOWNLOAD_OUTPUT" >> "$LOG_FILE"
40+
echo "$DOWNLOAD_OUTPUT"
41+
if echo "$DOWNLOAD_OUTPUT" | grep -q "Error"; then
42+
log "Failed to download model: $MODEL_ID"
43+
continue
44+
fi
45+
46+
# 部署服务
47+
log "Deploying..."
48+
DEPLOY_OUTPUT=$(s deploy 2>&1)
49+
echo "$DEPLOY_OUTPUT" >> "$LOG_FILE"
50+
echo "$DEPLOY_OUTPUT"
51+
52+
# 检查部署是否成功
53+
if echo "$DEPLOY_OUTPUT" | grep -q "state:.*Active"; then
54+
log "Deployment successful for model: $MODEL_ID"
55+
else
56+
log "Deployment failed for model: $MODEL_ID"
57+
# 清理资源
58+
REMOVE_OUTPUT=$(s model remove -y 2>&1)
59+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
60+
echo "$REMOVE_OUTPUT"
61+
REMOVE_OUTPUT=$(s remove -y 2>&1)
62+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
63+
echo "$REMOVE_OUTPUT"
64+
continue
65+
fi
66+
67+
# 提取system_url
68+
SYSTEM_URL=$(echo "$DEPLOY_OUTPUT" | grep "system_url:" | sed 's/.*system_url: *//' | tr -d ' "[:cntrl:]')
69+
if [ -z $SYSTEM_URL ]; then
70+
log "Failed to extract system_url for model: $MODEL_ID"
71+
# 清理资源
72+
REMOVE_OUTPUT=$(s model remove -y 2>&1)
73+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
74+
echo "$REMOVE_OUTPUT"
75+
REMOVE_OUTPUT=$(s remove -y 2>&1)
76+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
77+
echo "$REMOVE_OUTPUT"
78+
continue
79+
fi
80+
log "Extracted system_url: $SYSTEM_URL"
81+
82+
# 发送测试请求
83+
log "Sending test request..."
84+
CURL_OUTPUT=$(curl --request POST \
85+
--url "$SYSTEM_URL/v1/chat/completions" \
86+
-H "Content-Type: application/json" \
87+
--data '{
88+
"model": "$MODEL_ID",
89+
"messages": [
90+
{
91+
"role": "user",
92+
"content": "Hello! 你是谁?"
93+
}
94+
],
95+
"stream": false
96+
}' 2>&1)
97+
98+
echo "$CURL_OUTPUT" >> "$LOG_FILE"
99+
echo "$CURL_OUTPUT"
100+
101+
# 检查curl请求是否成功
102+
if echo "$CURL_OUTPUT" | grep -q '"object":"chat.completion"'; then
103+
log "Model test successful for: $MODEL_ID"
104+
# 提取并显示模型回复内容
105+
RESPONSE_CONTENT=$(echo "$CURL_OUTPUT" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p' | sed 's/\\n/\n/g' | sed 's/\\t/\t/g')
106+
log "Model response: $RESPONSE_CONTENT"
107+
else
108+
log "Model test failed for: $MODEL_ID"
109+
fi
110+
111+
# 清理资源
112+
log "Removing resources..."
113+
REMOVE_OUTPUT=$(s model remove -y 2>&1)
114+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
115+
echo "$REMOVE_OUTPUT"
116+
REMOVE_OUTPUT=$(s remove -y 2>&1)
117+
echo "$REMOVE_OUTPUT" >> "$LOG_FILE"
118+
echo "$REMOVE_OUTPUT"
119+
120+
log ""
121+
log "Finished testing model: $MODEL_ID"
122+
log ""
123+
done
124+
125+
log "All models tested."

package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"author": "",
2323
"license": "ISC",
2424
"dependencies": {
25+
"@alicloud/devs20230714": "^2.4.5",
2526
"@alicloud/fc2": "^2.6.6",
2627
"@alicloud/fc20230330": "4.3.4",
2728
"@alicloud/pop-core": "^1.8.0",
@@ -34,6 +35,7 @@
3435
"@serverless-devs/utils": "^0.0.17",
3536
"@serverless-devs/zip": "^0.0.3-beta.8",
3637
"ajv": "^8.17.1",
38+
"ali-oss": "6.18.1",
3739
"aliyun-sdk": "^1.12.10",
3840
"chalk": "^4.1.0",
3941
"crc64-ecma182.js": "^2.0.2",
@@ -51,8 +53,7 @@
5153
"temp-dir": "^2.0.0",
5254
"tty-table": "^4.2.3",
5355
"uuid": "^9.0.1",
54-
"uuid-by-string": "^4.0.0",
55-
"ali-oss": "6.18.1"
56+
"uuid-by-string": "^4.0.0"
5657
},
5758
"devDependencies": {
5859
"@serverless-devs/component-interface": "^0.0.6",

src/commands-help/model.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export default {
2+
help: {
3+
description: 'Resource layer operation ',
4+
summary: 'Resource layer operation ',
5+
},
6+
subCommands: {
7+
download: {
8+
help: {
9+
description: `Download model`,
10+
summary: 'Publish new layer version',
11+
option: [],
12+
},
13+
},
14+
reomve: {
15+
help: {
16+
description: `Remove model`,
17+
summary: 'Remove model',
18+
option: [],
19+
},
20+
},
21+
},
22+
};

src/default/resources.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ export const VPC_AND_NAS_NAME = process.env.FC_GENERATE_VPC_AND_NAS_NAME || defa
44
const defaultLogStoreName = 'default-logs';
55
export const PROJECT = process.env.FC_GENERATE_PROJECT_NAME;
66
export const LOG_STORE = process.env.FC_GENERATE_LOGSTORE_NAME || defaultLogStoreName;
7+
8+
export function getEnvVariable(key: string): string {
9+
if (typeof process !== 'undefined' && process.env) {
10+
return process.env[key] || '';
11+
}
12+
return '';
13+
}

src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import SYaml2To3 from './subCommands/2to3';
2525
import Logs from './subCommands/logs';
2626
import { SCHEMA_FILE_PATH } from './constant';
2727
import { checkDockerIsOK, isAppCenter, isYunXiao } from './utils';
28+
import { Model } from './subCommands/model';
2829

2930
export default class Fc extends Base {
3031
// 部署函数
@@ -168,6 +169,13 @@ export default class Fc extends Base {
168169
return await logs.run();
169170
}
170171

172+
public async model(inputs: IInputs) {
173+
await super.handlePreRun(inputs, false);
174+
const model = new Model(inputs);
175+
logger.debug(`model inputs: ${model.subCommand}`);
176+
return await model[model.subCommand]();
177+
}
178+
171179
public async getSchema(inputs: IInputs) {
172180
logger.debug(`getSchema: ${JSON.stringify(inputs)}`);
173181
return fs.readFileSync(SCHEMA_FILE_PATH, 'utf-8');

src/interface/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface IProps extends IFunction {
1919
concurrencyConfig?: IConcurrencyConfig;
2020
provisionConfig?: IProvisionConfig;
2121
endpoint?: string;
22+
supplement?: any;
2223
}
2324

2425
export interface IInputs extends _IInputs {

src/subCommands/deploy/impl/function.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import _ from 'lodash';
1+
import _, { isEmpty } from 'lodash';
22
import { diffConvertYaml } from '@serverless-devs/diff';
33
import inquirer from 'inquirer';
44
import fs from 'fs';
@@ -319,7 +319,7 @@ export default class Service extends Base {
319319
* 生成 auto 资源,非 FC 资源,主要指 vpc、nas、log、role(oss mount 挂载点才有)
320320
*/
321321
private async _deployAuto() {
322-
const { region } = this.inputs.props;
322+
const { region, supplement } = this.inputs.props;
323323
const { credential } = this.inputs;
324324
const { functionName } = this.local;
325325

@@ -390,14 +390,19 @@ vpcConfig:
390390
_.set(this.local, 'vpcConfig', vpcConfig);
391391
}
392392
if (nasAuto) {
393+
let modelConfig;
394+
if (!isEmpty(supplement)) {
395+
modelConfig = supplement.modelConfig;
396+
}
397+
393398
logger.write(
394399
yellow(`Created nas resource succeeded, please replace nasConfig: auto in yaml with:
395400
nasConfig:
396401
groupId: 0
397402
userId: 0
398403
mountPoints:
399-
- serverAddr: ${mountTargetDomain}:/${functionName}
400-
mountDir: /mnt/${functionName}
404+
- serverAddr: ${mountTargetDomain}:/${functionName}${isEmpty(modelConfig) ? '' : '/' + modelConfig.id}
405+
mountDir: /mnt/${functionName}${isEmpty(modelConfig) ? '' : '/' + modelConfig.id}
401406
enableTLS: false\n`),
402407
);
403408
this.createResource.nas = { mountTargetDomain, fileSystemId };
@@ -406,8 +411,8 @@ nasConfig:
406411
userId: 0,
407412
mountPoints: [
408413
{
409-
serverAddr: `${mountTargetDomain}:/${functionName}`,
410-
mountDir: `/mnt/${functionName}`,
414+
serverAddr: `${mountTargetDomain}:/${functionName}${isEmpty(modelConfig) ? '' : '/' + modelConfig.id}`,
415+
mountDir: `/mnt/${functionName}${isEmpty(modelConfig) ? '' : '/' + modelConfig.id}`,
411416
enableTLS: false,
412417
},
413418
],

0 commit comments

Comments
 (0)