Skip to content

Commit 44c7064

Browse files
Automate LLM Finetune Deepspeed demo
1 parent d444a3e commit 44c7064

File tree

9 files changed

+1302
-0
lines changed

9 files changed

+1302
-0
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ require (
1616
sigs.k8s.io/kueue v0.6.2
1717
)
1818

19+
replace github.com/project-codeflare/codeflare-common => /home/abdhumal/abhidev/RedHatDev/codeflare-common
20+
1921
require (
2022
github.com/aymerick/douceur v0.2.0 // indirect
2123
github.com/beorn7/perks v1.0.1 // indirect
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
Copyright 2023.
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+
http://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+
17+
package odh
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/gomega"
23+
. "github.com/project-codeflare/codeflare-common/support"
24+
rayv1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1"
25+
)
26+
27+
func TestRayFinetuneDemo(t *testing.T) {
28+
mnistRayLlmFinetune(t, 1)
29+
}
30+
31+
func mnistRayLlmFinetune(t *testing.T, numGpus int) {
32+
test := With(t)
33+
34+
// Create a namespace
35+
namespace := test.NewTestNamespace()
36+
37+
// Test configuration
38+
jupyterNotebookConfigMapFileName := "ray_finetune_llm_deepspeed.ipynb"
39+
40+
// Test configuration
41+
configMap := map[string][]byte{
42+
// MNIST Ray Notebook
43+
jupyterNotebookConfigMapFileName: ReadFile(test, "resources/ray_finetune_demo/ray_finetune_llm_deepspeed.ipynb"),
44+
"ray_finetune_llm_deepspeed.py": ReadFile(test, "resources/ray_finetune_demo/ray_finetune_llm_deepspeed.py"),
45+
"ray_finetune_requirements.txt": ReadRayFinetuneRequirementsTxt(test),
46+
"create_dataset.py": ReadFile(test, "resources/ray_finetune_demo/create_dataset.py"),
47+
"lora.json": ReadFile(test, "resources/ray_finetune_demo/lora.json"),
48+
"zero_3_llama_2_7b.json": ReadFile(test, "resources/ray_finetune_demo/zero_3_llama_2_7b.json"),
49+
"utils.py": ReadFile(test, "resources/ray_finetune_demo/utils.py"),
50+
}
51+
52+
config := CreateConfigMap(test, namespace.Name, configMap)
53+
54+
// Define the regular(non-admin) user
55+
userName := GetNotebookUserName(test)
56+
userToken := GetNotebookUserToken(test)
57+
58+
// Create role binding with Namespace specific admin cluster role
59+
CreateUserRoleBindingWithClusterRole(test, userName, namespace.Name, "admin")
60+
61+
// Create Notebook CR
62+
createNotebook(test, namespace, userToken, config.Name, jupyterNotebookConfigMapFileName, numGpus)
63+
64+
// Gracefully cleanup Notebook
65+
defer func() {
66+
deleteNotebook(test, namespace)
67+
test.Eventually(listNotebooks(test, namespace), TestTimeoutGpuProvisioning).Should(HaveLen(0))
68+
}()
69+
70+
// Make sure the RayCluster is created and running
71+
test.Eventually(RayClusters(test, namespace.Name), TestTimeoutGpuProvisioning).
72+
Should(
73+
And(
74+
HaveLen(1),
75+
ContainElement(WithTransform(RayClusterState, Equal(rayv1.Ready))),
76+
),
77+
)
78+
79+
// Make sure the RayCluster finishes and is deleted
80+
test.Eventually(RayClusters(test, namespace.Name), TestTimeoutGpuProvisioning).
81+
Should(HaveLen(0))
82+
}
83+
84+
func ReadRayFinetuneRequirementsTxt(test Test) []byte {
85+
// Read the requirements.txt from resources and perform replacements for custom values using go template
86+
props := struct {
87+
PipIndexUrl string
88+
PipTrustedHost string
89+
}{
90+
PipIndexUrl: "--index " + string(GetPipIndexURL()),
91+
}
92+
93+
// Provide trusted host only if defined
94+
if len(GetPipTrustedHost()) > 0 {
95+
props.PipTrustedHost = "--trusted-host " + GetPipTrustedHost()
96+
}
97+
98+
template, err := files.ReadFile("resources/ray_finetune_demo/ray_finetune_requirements.txt")
99+
test.Expect(err).NotTo(HaveOccurred())
100+
101+
return ParseTemplate(test, template, props)
102+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from datasets import load_dataset
2+
import json
3+
import os
4+
5+
dataset = load_dataset("gsm8k", "main")
6+
7+
dataset_splits = {"train": dataset["train"], "test": dataset["test"]}
8+
9+
10+
def main():
11+
if not os.path.exists("data"):
12+
os.mkdir("data")
13+
14+
with open("data/tokens.json", "w") as f:
15+
tokens = {}
16+
tokens["tokens"] = ["<START_Q>", "<END_Q>", "<START_A>", "<END_A>"]
17+
f.write(json.dumps(tokens))
18+
19+
for key, ds in dataset_splits.items():
20+
with open(f"data/{key}.jsonl", "w") as f:
21+
for item in ds:
22+
newitem = {}
23+
newitem["input"] = (
24+
f"<START_Q>{item['question']}<END_Q>"
25+
f"<START_A>{item['answer']}<END_A>"
26+
)
27+
f.write(json.dumps(newitem) + "\n")
28+
29+
30+
if __name__ == "__main__":
31+
main()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"r": 8,
3+
"lora_alpha": 16,
4+
"lora_dropout": 0.05,
5+
"target_modules": ["q_proj", "v_proj", "k_proj", "o_proj", "gate_proj", "up_proj", "down_proj", "embed_tokens", "lm_head"],
6+
"task_type": "CAUSAL_LM",
7+
"modules_to_save": [],
8+
"bias": "none",
9+
"fan_in_fan_out": false,
10+
"init_lora_weights": true
11+
}

0 commit comments

Comments
 (0)