jdforaging commited on
Commit
3fa7988
·
verified ·
1 Parent(s): 6eca1eb

Upload Trading notebooks

Browse files
Files changed (2) hide show
  1. project3.ipynb +388 -0
  2. project3.py +204 -0
project3.ipynb ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": [],
7
+ "machine_shape": "hm",
8
+ "gpuType": "A100"
9
+ },
10
+ "kernelspec": {
11
+ "name": "python3",
12
+ "display_name": "Python 3"
13
+ },
14
+ "language_info": {
15
+ "name": "python"
16
+ },
17
+ "accelerator": "GPU"
18
+ },
19
+ "cells": [
20
+ {
21
+ "cell_type": "markdown",
22
+ "source": [
23
+ "## Project 3: Write code to trade stocks\n",
24
+ "\n",
25
+ "### An example code generator by fine-tuning StarCoder2 using QLoRA\n",
26
+ "\n",
27
+ "NOTE: This is a toy example to illustrate the technique – please don’t use\n",
28
+ "any of this code to make trading decisions!\n",
29
+ "\n",
30
+ "Previously, we created a dataset and uploaded it to Hugging Face. Now we download the dataset and use it to fine-tune StarCoder2 using QLoRA.\n",
31
+ "\n",
32
+ "We'll see what kind of trade() functions our model can create before and after training."
33
+ ],
34
+ "metadata": {
35
+ "id": "GHsssBgWM_l0"
36
+ }
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "source": [
41
+ "# pip installs\n",
42
+ "\n",
43
+ "!pip install -q requests==2.31.0 torch peft bitsandbytes transformers trl accelerate sentencepiece wandb"
44
+ ],
45
+ "metadata": {
46
+ "id": "MDyR63OTNUJ6",
47
+ "colab": {
48
+ "base_uri": "https://localhost:8080/"
49
+ },
50
+ "outputId": "2515f54a-44c6-4ac2-b6a8-f41c57cf1ddb"
51
+ },
52
+ "execution_count": null,
53
+ "outputs": [
54
+ {
55
+ "output_type": "stream",
56
+ "name": "stdout",
57
+ "text": [
58
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m251.6/251.6 kB\u001b[0m \u001b[31m5.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
59
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m119.8/119.8 MB\u001b[0m \u001b[31m13.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
60
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m226.7/226.7 kB\u001b[0m \u001b[31m26.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
61
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m309.4/309.4 kB\u001b[0m \u001b[31m34.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
62
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.9/6.9 MB\u001b[0m \u001b[31m81.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
63
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.3/21.3 MB\u001b[0m \u001b[31m66.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
64
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m547.8/547.8 kB\u001b[0m \u001b[31m51.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
65
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m103.4/103.4 kB\u001b[0m \u001b[31m16.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
66
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m207.3/207.3 kB\u001b[0m \u001b[31m30.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
67
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m300.2/300.2 kB\u001b[0m \u001b[31m36.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
68
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.7/62.7 kB\u001b[0m \u001b[31m10.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
69
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.8/40.8 MB\u001b[0m \u001b[31m43.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
70
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m116.3/116.3 kB\u001b[0m \u001b[31m20.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
71
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m542.1/542.1 kB\u001b[0m \u001b[31m55.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
72
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m542.0/542.0 kB\u001b[0m \u001b[31m54.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
73
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m194.1/194.1 kB\u001b[0m \u001b[31m29.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
74
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.8/134.8 kB\u001b[0m \u001b[31m21.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
75
+ "\u001b[?25h"
76
+ ]
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "source": [
83
+ "# imports\n",
84
+ "\n",
85
+ "import os\n",
86
+ "from google.colab import userdata\n",
87
+ "from huggingface_hub import login\n",
88
+ "import torch\n",
89
+ "import transformers\n",
90
+ "from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TextStreamer, TrainingArguments\n",
91
+ "from datasets import load_dataset, Dataset\n",
92
+ "import wandb\n",
93
+ "from peft import LoraConfig\n",
94
+ "from trl import SFTTrainer, SFTConfig\n",
95
+ "from datetime import datetime"
96
+ ],
97
+ "metadata": {
98
+ "id": "-yikV8pRBer9"
99
+ },
100
+ "execution_count": null,
101
+ "outputs": []
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "source": [
106
+ "# Constants\n",
107
+ "\n",
108
+ "BASE_MODEL = \"bigcode/starcoder2-3b\" # choose 3b or 7b\n",
109
+ "PROJECT_NAME = \"trading\"\n",
110
+ "RUN_NAME = f\"{datetime.now():%Y-%m-%d_%H.%M.%S}\"\n",
111
+ "PROJECT_RUN_NAME = f\"{PROJECT_NAME}-{RUN_NAME}\"\n",
112
+ "DATASET_NAME = \"ed-donner/trade_code_dataset\"\n",
113
+ "\n",
114
+ "# Hyperparameters for QLoRA Fine-Tuning\n",
115
+ "# Details of QLoRA are out of scope for today, but there's\n",
116
+ "# more information and links in the resources\n",
117
+ "\n",
118
+ "EPOCHS = 1\n",
119
+ "LORA_ALPHA = 32\n",
120
+ "LORA_R = 16\n",
121
+ "LORA_DROPOUT = 0.1\n",
122
+ "BATCH_SIZE = 1\n",
123
+ "GRADIENT_ACCUMULATION_STEPS = 1\n",
124
+ "LEARNING_RATE = 2e-4\n",
125
+ "LR_SCHEDULER_TYPE = 'cosine'\n",
126
+ "WEIGHT_DECAY = 0.001\n",
127
+ "TARGET_MODULES = [\"q_proj\", \"v_proj\", \"k_proj\", \"o_proj\"]\n",
128
+ "MAX_SEQUENCE_LENGTH = 320\n",
129
+ "\n",
130
+ "# Other config\n",
131
+ "\n",
132
+ "STEPS = 10\n",
133
+ "SAVE_STEPS = 300"
134
+ ],
135
+ "metadata": {
136
+ "id": "uuTX-xonNeOK"
137
+ },
138
+ "execution_count": null,
139
+ "outputs": []
140
+ },
141
+ {
142
+ "cell_type": "markdown",
143
+ "source": [
144
+ "### Log in to HuggingFace and Weights & Biases\n",
145
+ "\n",
146
+ "If you don't already have a HuggingFace account, visit https://huggingface.co to sign up and create a token.\n",
147
+ "\n",
148
+ "Then select the Secrets for this Notebook by clicking on the key icon in the left, and add a new secret called `HF_TOKEN` with the value as your token.\n",
149
+ "\n",
150
+ "Repeat this for weightsandbiases at https://wandb.ai and add a secret called `WANDB_API_KEY`"
151
+ ],
152
+ "metadata": {
153
+ "id": "8JArT3QAQAjx"
154
+ }
155
+ },
156
+ {
157
+ "cell_type": "code",
158
+ "source": [
159
+ "# Log in to HuggingFace\n",
160
+ "\n",
161
+ "hf_token = userdata.get('HF_TOKEN')\n",
162
+ "login(hf_token, add_to_git_credential=True)"
163
+ ],
164
+ "metadata": {
165
+ "id": "WyFPZeMcM88v"
166
+ },
167
+ "execution_count": null,
168
+ "outputs": []
169
+ },
170
+ {
171
+ "cell_type": "code",
172
+ "source": [
173
+ "# Log in to Weights & Biases\n",
174
+ "wandb_api_key = userdata.get('WANDB_API_KEY')\n",
175
+ "os.environ[\"WANDB_API_KEY\"] = wandb_api_key\n",
176
+ "wandb.login()\n",
177
+ "\n",
178
+ "# Configure Weights & Biases to record against our project\n",
179
+ "os.environ[\"WANDB_PROJECT\"] = PROJECT_NAME\n",
180
+ "os.environ[\"WANDB_LOG_MODEL\"] = \"true\"\n",
181
+ "os.environ[\"WANDB_WATCH\"] = \"false\""
182
+ ],
183
+ "metadata": {
184
+ "id": "yJNOv3cVvJ68"
185
+ },
186
+ "execution_count": null,
187
+ "outputs": []
188
+ },
189
+ {
190
+ "cell_type": "markdown",
191
+ "source": [
192
+ "## Now load the Tokenizer and Model"
193
+ ],
194
+ "metadata": {
195
+ "id": "qJWQ0a3wZ0Bw"
196
+ }
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "source": [
201
+ "# Load the Tokenizer and the Model\n",
202
+ "\n",
203
+ "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)\n",
204
+ "tokenizer.pad_token = tokenizer.eos_token\n",
205
+ "tokenizer.padding_side = \"right\"\n",
206
+ "\n",
207
+ "quant_config = BitsAndBytesConfig(load_in_8bit=True)\n",
208
+ "\n",
209
+ "base_model = AutoModelForCausalLM.from_pretrained(\n",
210
+ " BASE_MODEL,\n",
211
+ " quantization_config=quant_config,\n",
212
+ " device_map=\"auto\",\n",
213
+ ")\n",
214
+ "base_model.generation_config.pad_token_id = tokenizer.pad_token_id\n",
215
+ "\n",
216
+ "print(f\"Memory footprint: {base_model.get_memory_footprint() / 1e6:.1f} MB\")"
217
+ ],
218
+ "metadata": {
219
+ "id": "R_O04fKxMMT-"
220
+ },
221
+ "execution_count": null,
222
+ "outputs": []
223
+ },
224
+ {
225
+ "cell_type": "markdown",
226
+ "source": [
227
+ "## Let's try out the model before we do fine-tuning"
228
+ ],
229
+ "metadata": {
230
+ "id": "UObo1-RqaNnT"
231
+ }
232
+ },
233
+ {
234
+ "cell_type": "code",
235
+ "source": [
236
+ "prompt = \"\"\"\n",
237
+ "# tickers is a list of stock tickers\n",
238
+ "import tickers\n",
239
+ "\n",
240
+ "# prices is a dict; the key is a ticker and the value is a list of historic prices, today first\n",
241
+ "import prices\n",
242
+ "\n",
243
+ "# Trade represents a decision to buy or sell a quantity of a ticker\n",
244
+ "import Trade\n",
245
+ "\n",
246
+ "import random\n",
247
+ "import numpy as np\n",
248
+ "\n",
249
+ "def trade():\n",
250
+ "\"\"\""
251
+ ],
252
+ "metadata": {
253
+ "id": "oaXOPhnySCcu"
254
+ },
255
+ "execution_count": null,
256
+ "outputs": []
257
+ },
258
+ {
259
+ "cell_type": "code",
260
+ "source": [
261
+ "from transformers import TextStreamer\n",
262
+ "streamer = TextStreamer(tokenizer)\n",
263
+ "\n",
264
+ "inputs = tokenizer.encode(prompt, return_tensors=\"pt\").to(\"cuda\")\n",
265
+ "outputs = base_model.generate(inputs, max_new_tokens=100, streamer=streamer)"
266
+ ],
267
+ "metadata": {
268
+ "id": "30lzJXBH7BcK"
269
+ },
270
+ "execution_count": null,
271
+ "outputs": []
272
+ },
273
+ {
274
+ "cell_type": "code",
275
+ "source": [
276
+ "# Load our dataset\n",
277
+ "dataset = load_dataset(DATASET_NAME)['train']\n",
278
+ "dataset"
279
+ ],
280
+ "metadata": {
281
+ "id": "kVcmuZVgAAgr"
282
+ },
283
+ "execution_count": null,
284
+ "outputs": []
285
+ },
286
+ {
287
+ "cell_type": "code",
288
+ "source": [
289
+ "# First, specify the configuration parameters for LoRA\n",
290
+ "\n",
291
+ "peft_parameters = LoraConfig(\n",
292
+ " lora_alpha=LORA_ALPHA,\n",
293
+ " lora_dropout=LORA_DROPOUT,\n",
294
+ " r=LORA_R,\n",
295
+ " bias=\"none\",\n",
296
+ " task_type=\"CAUSAL_LM\",\n",
297
+ " target_modules=TARGET_MODULES,\n",
298
+ ")\n",
299
+ "\n",
300
+ "# Next, specify the general configuration parameters for training\n",
301
+ "\n",
302
+ "train_params = SFTConfig(\n",
303
+ " output_dir=PROJECT_RUN_NAME,\n",
304
+ " num_train_epochs=EPOCHS,\n",
305
+ " per_device_train_batch_size=BATCH_SIZE,\n",
306
+ " per_device_eval_batch_size=1,\n",
307
+ " eval_strategy=\"no\",\n",
308
+ " gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,\n",
309
+ " optim=\"paged_adamw_32bit\",\n",
310
+ " save_steps=SAVE_STEPS,\n",
311
+ " save_total_limit=10,\n",
312
+ " logging_steps=STEPS,\n",
313
+ " learning_rate=LEARNING_RATE,\n",
314
+ " weight_decay=WEIGHT_DECAY,\n",
315
+ " fp16=False,\n",
316
+ " bf16=True,\n",
317
+ " max_grad_norm=0.3,\n",
318
+ " max_steps=-1,\n",
319
+ " warmup_ratio=0.03,\n",
320
+ " group_by_length=True,\n",
321
+ " lr_scheduler_type=LR_SCHEDULER_TYPE,\n",
322
+ " report_to=\"wandb\",\n",
323
+ " run_name=RUN_NAME,\n",
324
+ " max_seq_length=MAX_SEQUENCE_LENGTH,\n",
325
+ " dataset_text_field=\"text\",\n",
326
+ ")\n",
327
+ "\n",
328
+ "# And now, the Supervised Fine Tuning Trainer will carry out the fine-tuning\n",
329
+ "# Given these 2 sets of configuration parameters\n",
330
+ "\n",
331
+ "fine_tuning = SFTTrainer(\n",
332
+ " model=base_model,\n",
333
+ " train_dataset=dataset,\n",
334
+ " peft_config=peft_parameters,\n",
335
+ " tokenizer=tokenizer,\n",
336
+ " args=train_params\n",
337
+ ")\n",
338
+ "\n",
339
+ "# Fine-tune!\n",
340
+ "fine_tuning.train()\n",
341
+ "\n",
342
+ "# Push our fine-tuned model to Hugging Face\n",
343
+ "fine_tuning.model.push_to_hub(PROJECT_RUN_NAME, private=True)"
344
+ ],
345
+ "metadata": {
346
+ "id": "fCwmDmkSATvj"
347
+ },
348
+ "execution_count": null,
349
+ "outputs": []
350
+ },
351
+ {
352
+ "cell_type": "code",
353
+ "source": [
354
+ "# Code up a trade\n",
355
+ "\n",
356
+ "inputs = tokenizer.encode(prompt, return_tensors=\"pt\").to(\"cuda\")\n",
357
+ "outputs = fine_tuning.model.generate(inputs, max_new_tokens=120, streamer=streamer)"
358
+ ],
359
+ "metadata": {
360
+ "id": "3MGyNCSAFfy6"
361
+ },
362
+ "execution_count": null,
363
+ "outputs": []
364
+ },
365
+ {
366
+ "cell_type": "code",
367
+ "source": [
368
+ "# Another!\n",
369
+ "\n",
370
+ "outputs = fine_tuning.model.generate(inputs, max_new_tokens=120, streamer=streamer)"
371
+ ],
372
+ "metadata": {
373
+ "id": "chiHKzbRtHed"
374
+ },
375
+ "execution_count": null,
376
+ "outputs": []
377
+ },
378
+ {
379
+ "cell_type": "markdown",
380
+ "source": [
381
+ "## That's the example of QLoRA Fine Tuning to write code to carry out a specific function (but don't actually use this for trading!)"
382
+ ],
383
+ "metadata": {
384
+ "id": "QjktU3874KdY"
385
+ }
386
+ }
387
+ ]
388
+ }
project3.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """project3.ipynb
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/19E9hoAzWKvn9c9SHqM4Xan_Ph4wNewHS
8
+
9
+ ## Project 3: Write code to trade stocks
10
+
11
+ ### An example code generator by fine-tuning StarCoder2 using QLoRA
12
+
13
+ NOTE: This is a toy example to illustrate the technique – please don’t use
14
+ any of this code to make trading decisions!
15
+
16
+ Previously, we created a dataset and uploaded it to Hugging Face. Now we download the dataset and use it to fine-tune StarCoder2 using QLoRA.
17
+
18
+ We'll see what kind of trade() functions our model can create before and after training.
19
+ """
20
+
21
+ # pip installs
22
+
23
+ !pip install -q requests==2.31.0 torch peft bitsandbytes transformers trl accelerate sentencepiece wandb
24
+
25
+ # imports
26
+
27
+ import os
28
+ from google.colab import userdata
29
+ from huggingface_hub import login
30
+ import torch
31
+ import transformers
32
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TextStreamer, TrainingArguments
33
+ from datasets import load_dataset, Dataset
34
+ import wandb
35
+ from peft import LoraConfig
36
+ from trl import SFTTrainer, SFTConfig
37
+ from datetime import datetime
38
+
39
+ # Constants
40
+
41
+ BASE_MODEL = "bigcode/starcoder2-3b" # choose 3b or 7b
42
+ PROJECT_NAME = "trading"
43
+ RUN_NAME = f"{datetime.now():%Y-%m-%d_%H.%M.%S}"
44
+ PROJECT_RUN_NAME = f"{PROJECT_NAME}-{RUN_NAME}"
45
+ DATASET_NAME = "ed-donner/trade_code_dataset"
46
+
47
+ # Hyperparameters for QLoRA Fine-Tuning
48
+ # Details of QLoRA are out of scope for today, but there's
49
+ # more information and links in the resources
50
+
51
+ EPOCHS = 1
52
+ LORA_ALPHA = 32
53
+ LORA_R = 16
54
+ LORA_DROPOUT = 0.1
55
+ BATCH_SIZE = 1
56
+ GRADIENT_ACCUMULATION_STEPS = 1
57
+ LEARNING_RATE = 2e-4
58
+ LR_SCHEDULER_TYPE = 'cosine'
59
+ WEIGHT_DECAY = 0.001
60
+ TARGET_MODULES = ["q_proj", "v_proj", "k_proj", "o_proj"]
61
+ MAX_SEQUENCE_LENGTH = 320
62
+
63
+ # Other config
64
+
65
+ STEPS = 10
66
+ SAVE_STEPS = 300
67
+
68
+ """### Log in to HuggingFace and Weights & Biases
69
+
70
+ If you don't already have a HuggingFace account, visit https://huggingface.co to sign up and create a token.
71
+
72
+ Then select the Secrets for this Notebook by clicking on the key icon in the left, and add a new secret called `HF_TOKEN` with the value as your token.
73
+
74
+ Repeat this for weightsandbiases at https://wandb.ai and add a secret called `WANDB_API_KEY`
75
+ """
76
+
77
+ # Log in to HuggingFace
78
+
79
+ hf_token = userdata.get('HF_TOKEN')
80
+ login(hf_token, add_to_git_credential=True)
81
+
82
+ # Log in to Weights & Biases
83
+ wandb_api_key = userdata.get('WANDB_API_KEY')
84
+ os.environ["WANDB_API_KEY"] = wandb_api_key
85
+ wandb.login()
86
+
87
+ # Configure Weights & Biases to record against our project
88
+ os.environ["WANDB_PROJECT"] = PROJECT_NAME
89
+ os.environ["WANDB_LOG_MODEL"] = "true"
90
+ os.environ["WANDB_WATCH"] = "false"
91
+
92
+ """## Now load the Tokenizer and Model"""
93
+
94
+ # Load the Tokenizer and the Model
95
+
96
+ tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)
97
+ tokenizer.pad_token = tokenizer.eos_token
98
+ tokenizer.padding_side = "right"
99
+
100
+ quant_config = BitsAndBytesConfig(load_in_8bit=True)
101
+
102
+ base_model = AutoModelForCausalLM.from_pretrained(
103
+ BASE_MODEL,
104
+ quantization_config=quant_config,
105
+ device_map="auto",
106
+ )
107
+ base_model.generation_config.pad_token_id = tokenizer.pad_token_id
108
+
109
+ print(f"Memory footprint: {base_model.get_memory_footprint() / 1e6:.1f} MB")
110
+
111
+ """## Let's try out the model before we do fine-tuning"""
112
+
113
+ prompt = """
114
+ # tickers is a list of stock tickers
115
+ import tickers
116
+
117
+ # prices is a dict; the key is a ticker and the value is a list of historic prices, today first
118
+ import prices
119
+
120
+ # Trade represents a decision to buy or sell a quantity of a ticker
121
+ import Trade
122
+
123
+ import random
124
+ import numpy as np
125
+
126
+ def trade():
127
+ """
128
+
129
+ from transformers import TextStreamer
130
+ streamer = TextStreamer(tokenizer)
131
+
132
+ inputs = tokenizer.encode(prompt, return_tensors="pt").to("cuda")
133
+ outputs = base_model.generate(inputs, max_new_tokens=100, streamer=streamer)
134
+
135
+ # Load our dataset
136
+ dataset = load_dataset(DATASET_NAME)['train']
137
+ dataset
138
+
139
+ # First, specify the configuration parameters for LoRA
140
+
141
+ peft_parameters = LoraConfig(
142
+ lora_alpha=LORA_ALPHA,
143
+ lora_dropout=LORA_DROPOUT,
144
+ r=LORA_R,
145
+ bias="none",
146
+ task_type="CAUSAL_LM",
147
+ target_modules=TARGET_MODULES,
148
+ )
149
+
150
+ # Next, specify the general configuration parameters for training
151
+
152
+ train_params = SFTConfig(
153
+ output_dir=PROJECT_RUN_NAME,
154
+ num_train_epochs=EPOCHS,
155
+ per_device_train_batch_size=BATCH_SIZE,
156
+ per_device_eval_batch_size=1,
157
+ eval_strategy="no",
158
+ gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,
159
+ optim="paged_adamw_32bit",
160
+ save_steps=SAVE_STEPS,
161
+ save_total_limit=10,
162
+ logging_steps=STEPS,
163
+ learning_rate=LEARNING_RATE,
164
+ weight_decay=WEIGHT_DECAY,
165
+ fp16=False,
166
+ bf16=True,
167
+ max_grad_norm=0.3,
168
+ max_steps=-1,
169
+ warmup_ratio=0.03,
170
+ group_by_length=True,
171
+ lr_scheduler_type=LR_SCHEDULER_TYPE,
172
+ report_to="wandb",
173
+ run_name=RUN_NAME,
174
+ max_seq_length=MAX_SEQUENCE_LENGTH,
175
+ dataset_text_field="text",
176
+ )
177
+
178
+ # And now, the Supervised Fine Tuning Trainer will carry out the fine-tuning
179
+ # Given these 2 sets of configuration parameters
180
+
181
+ fine_tuning = SFTTrainer(
182
+ model=base_model,
183
+ train_dataset=dataset,
184
+ peft_config=peft_parameters,
185
+ tokenizer=tokenizer,
186
+ args=train_params
187
+ )
188
+
189
+ # Fine-tune!
190
+ fine_tuning.train()
191
+
192
+ # Push our fine-tuned model to Hugging Face
193
+ fine_tuning.model.push_to_hub(PROJECT_RUN_NAME, private=True)
194
+
195
+ # Code up a trade
196
+
197
+ inputs = tokenizer.encode(prompt, return_tensors="pt").to("cuda")
198
+ outputs = fine_tuning.model.generate(inputs, max_new_tokens=120, streamer=streamer)
199
+
200
+ # Another!
201
+
202
+ outputs = fine_tuning.model.generate(inputs, max_new_tokens=120, streamer=streamer)
203
+
204
+ """## That's the example of QLoRA Fine Tuning to write code to carry out a specific function (but don't actually use this for trading!)"""