tapxc3 commited on
Commit
d2dfd3d
·
verified ·
1 Parent(s): f51dfa6

Update train.py

Browse files
Files changed (1) hide show
  1. train.py +0 -205
train.py CHANGED
@@ -1,12 +1,5 @@
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
- import os
4
-
5
- # Avoid permission errors in Hugging Face Spaces
6
- os.environ["HF_HOME"] = "/workspace/.cache"
7
- os.environ["HF_DATASETS_CACHE"] = "/workspace/.cache/hf_datasets"
8
- os.environ["TRANSFORMERS_CACHE"] = "/workspace/.cache/hf_transformers"
9
-
10
  from datasets import load_dataset
11
  from trl import GRPOConfig, GRPOTrainer
12
  from transformers import AutoModelForCausalLM, AutoTokenizer
@@ -51,202 +44,4 @@ roman_to_int = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
51
  print("Connecting to ChromaDB...")
52
  chroma_client = HttpClient(host="34.126.200.250", port=8000)
53
  collection = chroma_client.get_collection(name="orwell_books")
54
- nlp = spacy.load("en_core_web_sm")
55
- phrase_matcher = PhraseMatcher(nlp.vocab, attr="LOWER")
56
- patterns = [nlp.make_doc(title) for title in BOOK_TITLES]
57
- phrase_matcher.add("BOOK_TITLE", patterns)
58
  print("Connected to ChromaDB.")
59
-
60
- def extract_metadata(prompt):
61
- metadata = {"$and": [{"title": None}]}
62
- doc = nlp(prompt)
63
- part_no = get_part_number(prompt)
64
- name = None
65
- matches = phrase_matcher(doc)
66
- for _, start, end in matches:
67
- span = doc[start:end]
68
- metadata["$and"][0]["title"] = span.text.lower()
69
- name = span.text.lower()
70
- break
71
- if part_no is not None:
72
- digit_word = digit_to_spelled[part_no]
73
- roman_word = digit_to_roman[part_no]
74
- chapter_filter = {
75
- "$or": [
76
- {"chapter": {"$in": [f"chapter {part_no}", f"part {part_no}", f"chapter {digit_word}", f"part {digit_word}", f"chapter {roman_word}"]}},
77
- {"subchapter": {"$in": [f"chapter {part_no}", f"part {part_no}", f"chapter {digit_word}", f"part {digit_word}", f"chapter {roman_word}"]}}
78
- ]
79
- }
80
- metadata["$and"].append(chapter_filter)
81
- else:
82
- metadata = {"title": name}
83
- return metadata, name
84
-
85
- def retrieve_context(prompt, top_k=1):
86
- filters, nameBook = extract_metadata(prompt)
87
- results = collection.query(
88
- query_texts=["Give me the book named " + nameBook],
89
- where=filters,
90
- n_results=top_k
91
- )
92
- if not results['documents'] or not results['documents'][0]:
93
- return [{"content": "No relevant context found.", "meta": {}}]
94
- return [
95
- {"content": doc, "meta": meta}
96
- for doc, meta in zip(results['documents'][0], results['metadatas'][0])
97
- ]
98
-
99
- def detect_question_type(user_prompt):
100
- prompt_lower = user_prompt.lower()
101
- if any(k in prompt_lower for k in ["mcq", "multiple choice"]): return "MCQs"
102
- if any(k in prompt_lower for k in ["essay", "long answer"]): return "Essay"
103
- if any(k in prompt_lower for k in ["short answer"]): return "Short Answer"
104
- if any(k in prompt_lower for k in ["paragraph"]): return "Paragraph Answer"
105
- if any(k in prompt_lower for k in ["passage"]): return "Passage-Based"
106
- if "quiz" in prompt_lower: return "Quiz"
107
- return "Short Answer"
108
-
109
- def roman_to_number(roman):
110
- total, prev_value = 0, 0
111
- for char in reversed(roman.upper()):
112
- value = roman_to_int.get(char, 0)
113
- total += -value if value < prev_value else value
114
- prev_value = value
115
- return total if total > 0 else None
116
-
117
- def get_part_number(prompt):
118
- doc = nlp(prompt)
119
- part_keywords = {"chapter", "part", "section"}
120
- number_pattern = re.compile(r"^\\d+$")
121
- roman_pattern = re.compile(r"^[IVXLCDM]+$", re.IGNORECASE)
122
- for i, token in enumerate(doc):
123
- token_lower = token.text.lower()
124
- if token_lower in spelled_to_digit or token_lower in ordinal_to_digit or roman_pattern.match(token_lower) or number_pattern.match(token_lower):
125
- for j in range(1, 3):
126
- if i + j < len(doc) and doc[i + j].text.lower() in part_keywords:
127
- return spelled_to_digit.get(token_lower) or ordinal_to_digit.get(token_lower) or int(token_lower) if number_pattern.match(token_lower) else roman_to_number(token_lower)
128
- elif token_lower in part_keywords:
129
- for j in range(1, 4):
130
- if i + j < len(doc):
131
- next_token = doc[i + j].text.lower()
132
- return spelled_to_digit.get(next_token) or ordinal_to_digit.get(next_token) or int(next_token) if number_pattern.match(next_token) else roman_to_number(next_token)
133
- return None
134
-
135
- def get_prompt(contexts, user_prompt=""):
136
- question_type = detect_question_type(user_prompt)
137
- citation_instr = """
138
- - Every question and explanation must include at least one **inline citation** in the format: [1]
139
- - Each inline citation must correspond to a **source reference at the end** of the response, using this exact format:
140
- [1] Book Title, Chapter X
141
- """
142
- if question_type == "MCQs":
143
- answer_block = (
144
- "Answer options:\n"
145
- " A. Option A\n"
146
- " B. Option B\n"
147
- " C. Option C\n"
148
- " D. Option D\n"
149
- )
150
- else:
151
- answer_block = ""
152
- output_format = f"""
153
- Question
154
- {answer_block}
155
- Supporting context
156
-
157
- Sources:
158
- [1] Book Title, Chapter X
159
- """
160
- prompt = f"""
161
- You are a literature teaching assistant. Generate one {question_type} question based on the context.
162
- {citation_instr}
163
-
164
- Context:
165
- {contexts[0]['content']}
166
-
167
- Now Complete:
168
- {output_format}
169
- """
170
- return prompt
171
-
172
- def make_format(example):
173
- return {
174
- "prompt": [
175
- {"role": "system", "content": get_prompt(retrieve_context(example["prompt"]), example["prompt"])} ,
176
- {"role": "user", "content": example["prompt"]},
177
- ],
178
- }
179
-
180
- def binary_reward(value): return 1.0 if value == "yes" else -1.0
181
-
182
- def normalize_rating(value, max_value=5): return value / max_value
183
-
184
- def compute_reward(sample):
185
- intent = binary_reward(sample.get("intent_relevance.responses", ["no"])[0])
186
- citation = binary_reward(sample.get("citation_support.responses", ["no"])[0])
187
- hallucination = binary_reward(sample.get("hallucination_check.responses", ["no"])[0])
188
- clarity = normalize_rating(sample.get("clarity_rating.responses", [0])[0])
189
- relevance = normalize_rating(sample.get("relevance_rating.responses", [0])[0])
190
- overall = normalize_rating(sample.get("overall_quality.responses", [0])[0])
191
- return 0.2*intent + 0.2*citation + 0.2*hallucination + 0.1*clarity + 0.15*relevance + 0.15*overall
192
-
193
- def add_reward(example):
194
- example["reward"] = compute_reward(example)
195
- return example
196
-
197
- def reward_calculate(completions, **kwargs):
198
- return kwargs["reward"]
199
-
200
- print("Loading raw dataset...")
201
- raw_dataset = load_dataset(DATA_ID, split="train")
202
- train_dataset = raw_dataset.map(make_format).map(add_reward).remove_columns([
203
- 'id', 'status', 'inserted_at', 'updated_at', '_server_id',
204
- 'intent_relevance.responses.users', 'intent_relevance.responses.status',
205
- 'citation_support.responses.users', 'citation_support.responses.status',
206
- 'hallucination_check.responses.users', 'hallucination_check.responses.status',
207
- 'clarity_rating.responses.users', 'clarity_rating.responses.status',
208
- 'relevance_rating.responses.users', 'relevance_rating.responses.status',
209
- 'overall_quality.responses.users', 'overall_quality.responses.status'])
210
-
211
- print("Loading model and tokenizer...")
212
- model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype="auto", device_map="auto")
213
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
214
- tokenizer.save_pretrained(MODEL_ID + "_test")
215
-
216
- print("Applying LoRA...")
217
- lora_config = LoraConfig(r=32, lora_alpha=64, target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM")
218
- model = get_peft_model(model, lora_config)
219
- model.print_trainable_parameters()
220
-
221
- print("Setting up GRPO training...")
222
- training_args = GRPOConfig(
223
- output_dir=MODEL_ID + "_test",
224
- learning_rate=2e-5,
225
- remove_unused_columns=False,
226
- gradient_accumulation_steps=16,
227
- num_train_epochs=3,
228
- bf16=True,
229
- max_completion_length=96,
230
- num_generations=4,
231
- max_prompt_length=256,
232
- report_to=["tensorboard"],
233
- logging_steps=10,
234
- push_to_hub=True,
235
- save_strategy="steps",
236
- save_steps=50,
237
- )
238
-
239
- trainer = GRPOTrainer(
240
- model=model,
241
- reward_funcs=reward_calculate,
242
- args=training_args,
243
- train_dataset=train_dataset
244
- )
245
-
246
- print("Starting training...")
247
- trainer.train()
248
-
249
- print("Saving and pushing model...")
250
- trainer.save_model(training_args.output_dir)
251
- trainer.push_to_hub(dataset_name=DATA_ID)
252
- print("Training complete and model uploaded!")
 
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
 
 
 
 
 
 
 
3
  from datasets import load_dataset
4
  from trl import GRPOConfig, GRPOTrainer
5
  from transformers import AutoModelForCausalLM, AutoTokenizer
 
44
  print("Connecting to ChromaDB...")
45
  chroma_client = HttpClient(host="34.126.200.250", port=8000)
46
  collection = chroma_client.get_collection(name="orwell_books")
 
 
 
 
47
  print("Connected to ChromaDB.")