flashrag-dev 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. flashrag/__init__.py +0 -0
  2. flashrag/config/__init__.py +2 -0
  3. flashrag/config/config.py +219 -0
  4. flashrag/dataset/__init__.py +2 -0
  5. flashrag/dataset/dataset.py +160 -0
  6. flashrag/dataset/utils.py +60 -0
  7. flashrag/evaluator/__init__.py +2 -0
  8. flashrag/evaluator/_bleu.py +209 -0
  9. flashrag/evaluator/evaluator.py +82 -0
  10. flashrag/evaluator/metrics.py +508 -0
  11. flashrag/evaluator/utils.py +19 -0
  12. flashrag/generator/__init__.py +2 -0
  13. flashrag/generator/fid.py +247 -0
  14. flashrag/generator/generator.py +623 -0
  15. flashrag/generator/openai_generator.py +96 -0
  16. flashrag/generator/stop_word_criteria.py +105 -0
  17. flashrag/judger/__init__.py +1 -0
  18. flashrag/judger/judger.py +184 -0
  19. flashrag/pipeline/__init__.py +3 -0
  20. flashrag/pipeline/active_pipeline.py +980 -0
  21. flashrag/pipeline/branching_pipeline.py +250 -0
  22. flashrag/pipeline/pipeline.py +248 -0
  23. flashrag/pipeline/replug_utils.py +249 -0
  24. flashrag/prompt/__init__.py +1 -0
  25. flashrag/prompt/base_prompt.py +165 -0
  26. flashrag/prompt/selfask_examplars.py +108 -0
  27. flashrag/prompt/trace_examplars.py +4015 -0
  28. flashrag/refiner/__init__.py +2 -0
  29. flashrag/refiner/kg_refiner.py +612 -0
  30. flashrag/refiner/llmlingua_compressor.py +2360 -0
  31. flashrag/refiner/refiner.py +252 -0
  32. flashrag/refiner/selective_context_compressor.py +294 -0
  33. flashrag/retriever/__init__.py +3 -0
  34. flashrag/retriever/__main__.py +4 -0
  35. flashrag/retriever/encoder.py +120 -0
  36. flashrag/retriever/index_builder.py +334 -0
  37. flashrag/retriever/reranker.py +145 -0
  38. flashrag/retriever/retriever.py +346 -0
  39. flashrag/retriever/utils.py +49 -0
  40. flashrag/utils/__init__.py +2 -0
  41. flashrag/utils/constants.py +51 -0
  42. flashrag/utils/pred_parse.py +25 -0
  43. flashrag/utils/utils.py +135 -0
  44. flashrag_dev-0.1.1.dist-info/LICENSE +21 -0
  45. flashrag_dev-0.1.1.dist-info/METADATA +616 -0
  46. flashrag_dev-0.1.1.dist-info/RECORD +48 -0
  47. flashrag_dev-0.1.1.dist-info/WHEEL +5 -0
  48. flashrag_dev-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,623 @@
1
+ from typing import List
2
+ from copy import deepcopy
3
+ from tqdm import tqdm
4
+ from tqdm.auto import trange
5
+ import numpy as np
6
+ import torch
7
+ from transformers import (
8
+ AutoTokenizer,
9
+ AutoModelForCausalLM,
10
+ T5ForConditionalGeneration,
11
+ BartForConditionalGeneration,
12
+ AutoConfig,
13
+ )
14
+
15
+
16
+ class BaseGenerator:
17
+ """`BaseGenerator` is a base object of Generator model."""
18
+
19
+ def __init__(self, config):
20
+ self.model_name = config["generator_model"]
21
+ self.model_path = config["generator_model_path"]
22
+
23
+ self.max_input_len = config["generator_max_input_len"]
24
+ self.batch_size = config["generator_batch_size"]
25
+ self.device = config["device"]
26
+ self.gpu_num = torch.cuda.device_count()
27
+
28
+ self.generation_params = config["generation_params"]
29
+
30
+ def generate(self, input_list: list) -> List[str]:
31
+ """Get responses from the generater.
32
+
33
+ Args:
34
+ input_list: it contains input texts, each item represents a sample.
35
+
36
+ Returns:
37
+ list: contains generator's response of each input sample.
38
+ """
39
+ pass
40
+
41
+
42
+ class EncoderDecoderGenerator(BaseGenerator):
43
+ """Class for encoder-decoder model"""
44
+
45
+ def __init__(self, config):
46
+ super().__init__(config)
47
+ self.fid = config["use_fid"]
48
+ model_config = AutoConfig.from_pretrained(self.model_path)
49
+ arch = model_config.architectures[0].lower()
50
+ if "t5" in arch:
51
+ if self.fid:
52
+ from flashrag.generator.fid import FiDT5
53
+
54
+ self.model = FiDT5.from_pretrained(self.model_path)
55
+ else:
56
+ self.model = T5ForConditionalGeneration.from_pretrained(
57
+ self.model_path
58
+ )
59
+ else:
60
+ if self.fid:
61
+ assert False, "FiD only support T5"
62
+ self.model = BartForConditionalGeneration.from_pretrained(
63
+ self.model_path
64
+ )
65
+ self.model.cuda()
66
+ self.model.eval()
67
+ self.tokenizer = AutoTokenizer.from_pretrained(self.model_path)
68
+
69
+ def encode_passages(self, batch_text_passages: List[List[str]]):
70
+ passage_ids, passage_masks = [], []
71
+ for k, text_passages in enumerate(batch_text_passages):
72
+ p = self.tokenizer.batch_encode_plus(
73
+ text_passages,
74
+ max_length=self.max_input_len,
75
+ pad_to_max_length=True,
76
+ return_tensors="pt",
77
+ truncation=True,
78
+ )
79
+ passage_ids.append(p["input_ids"][None])
80
+ passage_masks.append(p["attention_mask"][None])
81
+
82
+ passage_ids = torch.cat(passage_ids, dim=0)
83
+ passage_masks = torch.cat(passage_masks, dim=0)
84
+ return passage_ids, passage_masks.bool()
85
+
86
+ @torch.inference_mode(mode=True)
87
+ def generate(self, input_list: List, batch_size=None, **params):
88
+ if isinstance(input_list, str):
89
+ input_list = [input_list]
90
+ if batch_size is None:
91
+ batch_size = self.batch_size
92
+
93
+ generation_params = deepcopy(self.generation_params)
94
+ generation_params.update(params)
95
+
96
+ # deal stop params
97
+ stop_sym = None
98
+ if "stop" in generation_params:
99
+ from flashrag.generator.stop_word_criteria import StopWordCriteria
100
+
101
+ stop_sym = generation_params.pop("stop")
102
+ stopping_criteria = [
103
+ StopWordCriteria(
104
+ tokenizer=self.tokenizer,
105
+ prompts=input_list,
106
+ stop_words=stop_sym,
107
+ )
108
+ ]
109
+ generation_params["stopping_criteria"] = stopping_criteria
110
+
111
+ max_tokens = params.pop("max_tokens", None) or params.pop(
112
+ "max_new_tokens", None
113
+ )
114
+ if max_tokens is not None:
115
+ generation_params["max_new_tokens"] = max_tokens
116
+ else:
117
+ generation_params["max_new_tokens"] = generation_params.get(
118
+ "max_new_tokens", generation_params.pop("max_tokens", None)
119
+ )
120
+ generation_params.pop("max_tokens", None)
121
+
122
+ responses = []
123
+ for idx in trange(
124
+ 0, len(input_list), batch_size, desc="Generation process: "
125
+ ):
126
+ batched_prompts = input_list[idx : idx + batch_size]
127
+ if self.fid:
128
+ # assume each input in input_list is a list, contains K string
129
+ input_ids, attention_mask = self.encode_passages(
130
+ batched_prompts
131
+ )
132
+ inputs = {
133
+ "input_ids": input_ids.to(self.device),
134
+ "attention_mask": attention_mask.to(self.device),
135
+ }
136
+ else:
137
+ inputs = self.tokenizer(
138
+ batched_prompts,
139
+ return_tensors="pt",
140
+ padding=True,
141
+ truncation=True,
142
+ max_length=self.max_input_len,
143
+ ).to(self.device)
144
+
145
+ # TODO: multi-gpu inference
146
+ outputs = self.model.generate(**inputs, **generation_params)
147
+
148
+ outputs = self.tokenizer.batch_decode(
149
+ outputs,
150
+ skip_special_tokens=True,
151
+ clean_up_tokenization_spaces=False,
152
+ )
153
+
154
+ responses += outputs
155
+
156
+ return responses
157
+
158
+
159
+ class VLLMGenerator(BaseGenerator):
160
+ """Class for decoder-only generator, based on vllm."""
161
+
162
+ def __init__(self, config):
163
+ super().__init__(config)
164
+
165
+ from vllm import LLM
166
+
167
+ if "gpu_memory_utilization" not in config:
168
+ gpu_memory_utilization = 0.85
169
+ else:
170
+ gpu_memory_utilization = config["gpu_memory_utilization"]
171
+ if self.gpu_num != 1 and self.gpu_num % 2 != 0:
172
+ tensor_parallel_size = self.gpu_num - 1
173
+ else:
174
+ tensor_parallel_size = self.gpu_num
175
+
176
+ self.lora_path = (
177
+ None
178
+ if "generator_lora_path" not in config
179
+ else config["generator_lora_path"]
180
+ )
181
+ self.use_lora = False
182
+ if self.lora_path is not None:
183
+ self.use_lora = True
184
+ if self.use_lora:
185
+ self.model = LLM(
186
+ self.model_path,
187
+ tensor_parallel_size=tensor_parallel_size,
188
+ gpu_memory_utilization=gpu_memory_utilization,
189
+ enable_lora=True,
190
+ max_lora_rank=64,
191
+ max_logprobs=32016,
192
+ )
193
+ else:
194
+ self.model = LLM(
195
+ self.model_path,
196
+ tensor_parallel_size=tensor_parallel_size,
197
+ gpu_memory_utilization=gpu_memory_utilization,
198
+ max_logprobs=32016,
199
+ )
200
+ self.tokenizer = AutoTokenizer.from_pretrained(
201
+ self.model_path, trust_remote_code=True
202
+ )
203
+
204
+ @torch.inference_mode(mode=True)
205
+ def generate(
206
+ self,
207
+ input_list: List[str],
208
+ return_raw_output=False,
209
+ return_scores=False,
210
+ **params,
211
+ ):
212
+ from vllm import SamplingParams
213
+
214
+ if isinstance(input_list, str):
215
+ input_list = [input_list]
216
+
217
+ generation_params = deepcopy(self.generation_params)
218
+ generation_params.update(params)
219
+ if "do_sample" in generation_params:
220
+ generation_params.pop("do_sample")
221
+
222
+ max_tokens = params.pop("max_tokens", None) or params.pop(
223
+ "max_new_tokens", None
224
+ )
225
+ if max_tokens is not None:
226
+ generation_params["max_tokens"] = max_tokens
227
+ else:
228
+ generation_params["max_tokens"] = generation_params.get(
229
+ "max_tokens", generation_params.pop("max_new_tokens", None)
230
+ )
231
+ generation_params.pop("max_new_tokens", None)
232
+
233
+ # fix for llama3
234
+ if "stop" in generation_params:
235
+ generation_params["stop"].append("<|eot_id|>")
236
+ else:
237
+ generation_params["stop"] = ["<|eot_id|>"]
238
+
239
+ if return_scores:
240
+ if "logprobs" not in generation_params:
241
+ generation_params["logprobs"] = 100
242
+
243
+ sampling_params = SamplingParams(**generation_params)
244
+
245
+ if self.use_lora:
246
+ from vllm.lora.request import LoRARequest
247
+
248
+ outputs = self.model.generate(
249
+ input_list,
250
+ sampling_params,
251
+ lora_request=LoRARequest("lora_module", 1, self.lora_path),
252
+ )
253
+ else:
254
+ outputs = self.model.generate(input_list, sampling_params)
255
+
256
+ if return_raw_output:
257
+ base_output = outputs
258
+ else:
259
+ generated_texts = [output.outputs[0].text for output in outputs]
260
+ base_output = generated_texts
261
+ if return_scores:
262
+ scores = []
263
+ for output in outputs:
264
+ logprobs = output.outputs[0].logprobs
265
+ scores.append(
266
+ [
267
+ np.exp(list(score_dict.values())[0].logprob)
268
+ for score_dict in logprobs
269
+ ]
270
+ )
271
+ return base_output, scores
272
+ else:
273
+ return base_output
274
+
275
+
276
+ class HFCausalLMGenerator(BaseGenerator):
277
+ """Class for decoder-only generator, based on hf."""
278
+
279
+ def __init__(self, config, model=None):
280
+ super().__init__(config)
281
+ self.config = config
282
+ lora_path = (
283
+ None
284
+ if "generator_lora_path" not in config
285
+ else config["generator_lora_path"]
286
+ )
287
+ self.model, self.tokenizer = self._load_model(model=model)
288
+ self.use_lora = False
289
+ if lora_path is not None:
290
+ self.use_lora = True
291
+ self.model.load_adapter(lora_path)
292
+
293
+ def _load_model(self, model=None):
294
+ r"""Load model and tokenizer for generator."""
295
+ if model is None:
296
+ model = AutoModelForCausalLM.from_pretrained(
297
+ self.model_path,
298
+ torch_dtype="auto",
299
+ device_map="auto",
300
+ trust_remote_code=True,
301
+ )
302
+ else:
303
+ model.cuda()
304
+ model.eval()
305
+ tokenizer = AutoTokenizer.from_pretrained(
306
+ self.model_path, trust_remote_code=True
307
+ )
308
+ if "qwen" not in self.model_name:
309
+ tokenizer.pad_token = tokenizer.eos_token
310
+ tokenizer.padding_side = "left"
311
+
312
+ return model, tokenizer
313
+
314
+ def add_new_tokens(
315
+ self, token_embedding_path, token_name_func=lambda idx: f"[ref{idx+1}]"
316
+ ):
317
+ del self.model
318
+ self.model = AutoModelForCausalLM.from_pretrained(
319
+ self.model_path,
320
+ trust_remote_code=True,
321
+ )
322
+ # get original embedding weight matrix
323
+ embedding_layer = self.model.get_input_embeddings()
324
+ embedding_weights = embedding_layer.weight
325
+ original_vocab_size, embedding_dim = embedding_weights.shape
326
+
327
+ new_tokens_weights = torch.load(token_embedding_path)
328
+ new_tokens_length = new_tokens_weights.shape[0]
329
+
330
+ # expand vocabulary
331
+ new_tokens = [token_name_func(idx) for idx in range(new_tokens_length)]
332
+ self.tokenizer.add_tokens(new_tokens)
333
+
334
+ # create new embedding matrix
335
+ new_vocab_size = original_vocab_size + new_tokens_length
336
+ new_embedding_weights = torch.zeros(new_vocab_size, embedding_dim)
337
+
338
+ # copy original embeddings to the new weights
339
+ new_embedding_weights[:original_vocab_size, :] = embedding_weights
340
+
341
+ # append virtual token embeddings to the new weights
342
+ for token, embedding in zip(new_tokens, new_tokens_weights):
343
+ token_id = self.tokenizer.convert_tokens_to_ids(token)
344
+ new_embedding_weights[token_id] = embedding
345
+
346
+ # update the embedding table
347
+ # note: we should avoid using the function resize_token_embeddings() because this function will also change the lm_head of the model
348
+ embedding_layer.weight.data = new_embedding_weights
349
+ self.model.eval()
350
+ self.model.cuda()
351
+
352
+ @torch.inference_mode(mode=True)
353
+ def generate(
354
+ self,
355
+ input_list: List[str],
356
+ batch_size=None,
357
+ return_scores=False,
358
+ return_dict=False,
359
+ **params,
360
+ ):
361
+ """Generate batches one by one. The generated content needs to exclude input."""
362
+
363
+ if isinstance(input_list, str):
364
+ input_list = [input_list]
365
+ if batch_size is None:
366
+ batch_size = self.batch_size
367
+
368
+ generation_params = deepcopy(self.generation_params)
369
+ generation_params.update(params)
370
+
371
+ # deal stop params
372
+ stop_sym = None
373
+ if "stop" in generation_params:
374
+ from flashrag.generator.stop_word_criteria import StopWordCriteria
375
+
376
+ stop_sym = generation_params.pop("stop")
377
+ stopping_criteria = [
378
+ StopWordCriteria(
379
+ tokenizer=self.tokenizer,
380
+ prompts=input_list,
381
+ stop_words=stop_sym,
382
+ )
383
+ ]
384
+ generation_params["stopping_criteria"] = stopping_criteria
385
+
386
+ max_tokens = params.pop("max_tokens", None) or params.pop(
387
+ "max_new_tokens", None
388
+ )
389
+ if max_tokens is not None:
390
+ generation_params["max_new_tokens"] = max_tokens
391
+ else:
392
+ generation_params["max_new_tokens"] = generation_params.get(
393
+ "max_new_tokens", generation_params.pop("max_tokens", None)
394
+ )
395
+ generation_params.pop("max_tokens", None)
396
+
397
+ # set eos token for llama
398
+ if "llama" in self.model_name.lower():
399
+ extra_eos_tokens = [
400
+ self.tokenizer.eos_token_id,
401
+ self.tokenizer.convert_tokens_to_ids("<|eot_id|>"),
402
+ ]
403
+ if "eos_token_id" in generation_params:
404
+ generation_params["eos_token_id"].extend(extra_eos_tokens)
405
+ else:
406
+ generation_params["eos_token_id"] = extra_eos_tokens
407
+
408
+ responses = []
409
+ scores = []
410
+ generated_token_ids = []
411
+ generated_token_logits = []
412
+
413
+ for idx in trange(
414
+ 0, len(input_list), batch_size, desc="Generation process: "
415
+ ):
416
+ torch.cuda.empty_cache()
417
+ batched_prompts = input_list[idx : idx + batch_size]
418
+ inputs = self.tokenizer(
419
+ batched_prompts,
420
+ return_tensors="pt",
421
+ padding=True,
422
+ truncation=True,
423
+ max_length=self.max_input_len,
424
+ ).to(self.model.device)
425
+ outputs = self.model.generate(
426
+ **inputs,
427
+ output_scores=True,
428
+ return_dict_in_generate=True,
429
+ **generation_params,
430
+ )
431
+
432
+ generated_ids = outputs.sequences
433
+ logits = torch.stack(outputs.scores, dim=1).softmax(-1)
434
+ generated_ids = generated_ids[:, inputs["input_ids"].shape[-1] :]
435
+ gen_score = (
436
+ torch.gather(logits, 2, generated_ids[:, :, None])
437
+ .squeeze(-1)
438
+ .cpu()
439
+ .tolist()
440
+ )
441
+ scores.extend(gen_score)
442
+
443
+ # get additinoal info
444
+ if return_dict:
445
+ batch_generated_token_ids = generated_ids.detach().cpu()
446
+ batch_generated_token_logits = (
447
+ torch.cat(
448
+ [
449
+ token_scores.unsqueeze(1)
450
+ for token_scores in outputs.scores
451
+ ],
452
+ dim=1,
453
+ )
454
+ .detach()
455
+ .cpu()
456
+ )
457
+ if (
458
+ batch_generated_token_ids.shape[1]
459
+ < generation_params["max_new_tokens"]
460
+ ):
461
+ real_batch_size, num_generated_tokens = (
462
+ batch_generated_token_ids.shape
463
+ )
464
+ padding_length = (
465
+ generation_params["max_new_tokens"]
466
+ - num_generated_tokens
467
+ )
468
+ padding_token_ids = torch.zeros(
469
+ (real_batch_size, padding_length),
470
+ dtype=batch_generated_token_ids.dtype,
471
+ ).fill_(self.tokenizer.pad_token_id)
472
+ padding_token_logits = torch.zeros(
473
+ (
474
+ real_batch_size,
475
+ padding_length,
476
+ batch_generated_token_logits.shape[-1],
477
+ ),
478
+ dtype=batch_generated_token_logits.dtype,
479
+ )
480
+ batch_generated_token_ids = torch.cat(
481
+ [batch_generated_token_ids, padding_token_ids], dim=1
482
+ )
483
+ batch_generated_token_logits = torch.cat(
484
+ [batch_generated_token_logits, padding_token_logits],
485
+ dim=1,
486
+ )
487
+ generated_token_ids.append(batch_generated_token_ids)
488
+ generated_token_logits.append(batch_generated_token_logits)
489
+
490
+ for i, generated_sequence in enumerate(outputs.sequences):
491
+ input_ids = inputs["input_ids"][i]
492
+ text = self.tokenizer.decode(
493
+ generated_sequence,
494
+ skip_special_tokens=True,
495
+ clean_up_tokenization_spaces=False,
496
+ )
497
+ if input_ids is None:
498
+ prompt_length = 0
499
+ else:
500
+ prompt_length = len(
501
+ self.tokenizer.decode(
502
+ input_ids,
503
+ skip_special_tokens=True,
504
+ clean_up_tokenization_spaces=False,
505
+ )
506
+ )
507
+ new_text = text[prompt_length:]
508
+
509
+ if stop_sym is not None:
510
+ strip_stopword = True
511
+ # Find the first occurrence of any stop word
512
+ lower_stop_index = len(new_text) # Default to end of text
513
+ for sym in stop_sym:
514
+ stop_index = new_text.find(sym)
515
+ if stop_index != -1:
516
+ # Adjust stop index based on whether we're stripping the stop word
517
+ stop_index += 0 if strip_stopword else len(sym)
518
+ lower_stop_index = min(stop_index, lower_stop_index)
519
+
520
+ # Cut the text at the first stop word found (if any)
521
+ new_text = new_text[:lower_stop_index]
522
+
523
+ responses.append(new_text.strip())
524
+
525
+ if return_dict:
526
+ generated_token_ids = torch.cat(generated_token_ids, dim=0)
527
+ generated_token_logits = torch.cat(generated_token_logits, dim=0)
528
+ return {
529
+ "generated_token_ids": generated_token_ids,
530
+ "generated_token_logits": generated_token_logits,
531
+ "responses": responses,
532
+ "scores": scores,
533
+ }
534
+
535
+ if return_scores:
536
+ return responses, scores
537
+ else:
538
+ return responses
539
+
540
+ @torch.inference_mode(mode=True)
541
+ def cal_gen_probs(self, prev, next):
542
+ input_ids = self.tokenizer.encode(prev, add_special_tokens=False)
543
+ target_ids = self.tokenizer.encode(next, add_special_tokens=False)
544
+ context_ids = input_ids + target_ids
545
+ context_tensor = torch.tensor([context_ids]).to(self.device)
546
+ with torch.no_grad():
547
+ outputs = self.model(context_tensor)
548
+ logits = outputs.logits
549
+ logits = logits[0, len(input_ids) - 1 : len(context_ids) - 1, :]
550
+ logits = logits.to(torch.float32).detach().cpu()
551
+ # softmax to normalize
552
+ probs = torch.softmax(logits, dim=-1)
553
+ # obtain probs of target_ids
554
+ target_probs = probs[range(len(target_ids)), target_ids].numpy()
555
+
556
+ return logits, target_probs
557
+
558
+
559
+ class FastChatGenerator(HFCausalLMGenerator):
560
+ def __init__(self, config, model=None):
561
+ super().__init__(config)
562
+
563
+ def _load_model(self, model=None):
564
+ r"""Load model and tokenizer for generator."""
565
+
566
+ def get_gpu_memory(max_gpus=None):
567
+ """Get available memory for each GPU."""
568
+ gpu_memory = []
569
+ num_gpus = (
570
+ torch.cuda.device_count()
571
+ if max_gpus is None
572
+ else min(max_gpus, torch.cuda.device_count())
573
+ )
574
+ for gpu_id in range(num_gpus):
575
+ with torch.cuda.device(gpu_id):
576
+ device = torch.cuda.current_device()
577
+ gpu_properties = torch.cuda.get_device_properties(device)
578
+ total_memory = gpu_properties.total_memory / (1024**3)
579
+ allocated_memory = torch.cuda.memory_allocated() / (1024**3)
580
+ available_memory = total_memory - allocated_memory
581
+ gpu_memory.append(available_memory)
582
+ return gpu_memory
583
+
584
+ if model is None:
585
+ from fastchat.model import load_model
586
+
587
+ if "gpu_memory_utilization" not in self.config:
588
+ gpu_memory_utilization = 0.85
589
+ else:
590
+ gpu_memory_utilization = self.config["gpu_memory_utilization"]
591
+ max_gpu_memory = None
592
+ if self.gpu_num != 1:
593
+ available_gpu_memory = get_gpu_memory(self.gpu_num)
594
+ max_gpu_memory = (
595
+ str(int(min(available_gpu_memory) * gpu_memory_utilization))
596
+ + "GiB"
597
+ )
598
+
599
+ model, tokenizer = load_model(
600
+ self.model_path,
601
+ device="cuda",
602
+ num_gpus=self.gpu_num,
603
+ max_gpu_memory=max_gpu_memory,
604
+ load_8bit=False,
605
+ cpu_offloading=False,
606
+ debug=False,
607
+ )
608
+
609
+ else:
610
+ model.cuda()
611
+ tokenizer = AutoTokenizer.from_pretrained(
612
+ self.model_path, trust_remote_code=True
613
+ )
614
+ model.eval()
615
+
616
+ tokenizer = AutoTokenizer.from_pretrained(
617
+ self.model_path, trust_remote_code=True
618
+ )
619
+ if "qwen" not in self.model_name:
620
+ tokenizer.pad_token = tokenizer.eos_token
621
+ tokenizer.padding_side = "left"
622
+
623
+ return model, tokenizer