flashrag-dev 0.1.3.dev20241108__tar.gz → 0.1.3.dev20241111__tar.gz

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 (60) hide show
  1. {flashrag-dev-0.1.3.dev20241108/flashrag_dev.egg-info → flashrag-dev-0.1.3.dev20241111}/PKG-INFO +1 -1
  2. flashrag-dev-0.1.3.dev20241111/flashrag/dataset/dataset.py +180 -0
  3. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/dataset/utils.py +20 -12
  4. flashrag-dev-0.1.3.dev20241111/flashrag/generator/__init__.py +3 -0
  5. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/generator/generator.py +34 -115
  6. flashrag-dev-0.1.3.dev20241111/flashrag/generator/utils.py +67 -0
  7. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/encoder.py +44 -6
  8. flashrag-dev-0.1.3.dev20241111/flashrag/version.py +1 -0
  9. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111/flashrag_dev.egg-info}/PKG-INFO +1 -1
  10. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag_dev.egg-info/SOURCES.txt +1 -0
  11. flashrag-dev-0.1.3.dev20241108/flashrag/dataset/dataset.py +0 -160
  12. flashrag-dev-0.1.3.dev20241108/flashrag/generator/__init__.py +0 -2
  13. flashrag-dev-0.1.3.dev20241108/flashrag/version.py +0 -1
  14. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/LICENSE +0 -0
  15. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/README.md +0 -0
  16. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/__init__.py +0 -0
  17. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/config/__init__.py +0 -0
  18. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/config/basic_config.yaml +0 -0
  19. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/config/config.py +0 -0
  20. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/dataset/__init__.py +0 -0
  21. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/evaluator/__init__.py +0 -0
  22. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/evaluator/_bleu.py +0 -0
  23. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/evaluator/evaluator.py +0 -0
  24. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/evaluator/metrics.py +0 -0
  25. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/evaluator/utils.py +0 -0
  26. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/generator/fid.py +0 -0
  27. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/generator/openai_generator.py +0 -0
  28. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/generator/stop_word_criteria.py +0 -0
  29. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/judger/__init__.py +0 -0
  30. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/judger/judger.py +0 -0
  31. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/pipeline/__init__.py +0 -0
  32. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/pipeline/active_pipeline.py +0 -0
  33. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/pipeline/branching_pipeline.py +0 -0
  34. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/pipeline/pipeline.py +0 -0
  35. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/pipeline/replug_utils.py +0 -0
  36. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/prompt/__init__.py +0 -0
  37. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/prompt/base_prompt.py +0 -0
  38. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/prompt/selfask_examplars.py +0 -0
  39. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/prompt/trace_examplars.py +0 -0
  40. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/refiner/__init__.py +0 -0
  41. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/refiner/kg_refiner.py +0 -0
  42. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/refiner/llmlingua_compressor.py +0 -0
  43. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/refiner/refiner.py +0 -0
  44. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/refiner/selective_context_compressor.py +0 -0
  45. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/__init__.py +0 -0
  46. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/__main__.py +0 -0
  47. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/index_builder.py +0 -0
  48. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/reranker.py +0 -0
  49. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/retriever.py +0 -0
  50. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/retriever/utils.py +0 -0
  51. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/utils/__init__.py +0 -0
  52. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/utils/constants.py +0 -0
  53. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/utils/pred_parse.py +0 -0
  54. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag/utils/utils.py +0 -0
  55. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag_dev.egg-info/dependency_links.txt +0 -0
  56. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag_dev.egg-info/requires.txt +0 -0
  57. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/flashrag_dev.egg-info/top_level.txt +0 -0
  58. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/pyproject.toml +0 -0
  59. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/setup.cfg +0 -0
  60. {flashrag-dev-0.1.3.dev20241108 → flashrag-dev-0.1.3.dev20241111}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flashrag-dev
3
- Version: 0.1.3.dev20241108
3
+ Version: 0.1.3.dev20241111
4
4
  Summary: A library for efficient Retrieval-Augmented Generation research
5
5
  Home-page: https://github.com/RUC-NLPIR/FlashRAG
6
6
  Author: Jiajie Jin, Yutao Zhu, Chenghao Zhang, Xinyu Yang, Zhicheng Dou
@@ -0,0 +1,180 @@
1
+ import os
2
+ import json
3
+ import random
4
+ import warnings
5
+ from typing import List, Dict, Any, Optional, Generator
6
+ import numpy as np
7
+
8
+
9
+ class Item:
10
+ """A container class used to store and manipulate a sample within a dataset.
11
+ Information related to this sample during training/inference will be stored in `self.output`.
12
+ Each attribute of this class can be used like a dict key (also for key in `self.output`).
13
+ """
14
+
15
+ def __init__(self, item_dict: Dict[str, Any]) -> None:
16
+ self.id: Optional[str] = item_dict.get("id", None)
17
+ self.question: Optional[str] = item_dict.get("question", None)
18
+ self.golden_answers: List[str] = item_dict.get("golden_answers", [])
19
+ self.choices: List[str] = item_dict.get("choices", [])
20
+ self.metadata: Dict[str, Any] = item_dict.get("metadata", {})
21
+ self.output: Dict[str, Any] = item_dict.get("output", {})
22
+ self.data: Dict[str, Any] = item_dict
23
+
24
+ def update_output(self, key: str, value: Any) -> None:
25
+ """Update the output dict and keep a key in self.output can be used as an attribute."""
26
+ if key in ["id", "question", "golden_answers", "output", "choices"]:
27
+ raise AttributeError(f"{key} should not be changed")
28
+ else:
29
+ self.output[key] = value
30
+
31
+ def update_evaluation_score(self, metric_name: str, metric_score: float) -> None:
32
+ """Update the evaluation score of this sample for a metric."""
33
+ if "metric_score" not in self.output:
34
+ self.output["metric_score"] = {}
35
+ self.output["metric_score"][metric_name] = metric_score
36
+
37
+ def __getattr__(self, attr_name: str) -> Any:
38
+ predefined_attrs = ["id", "question", "golden_answers", "metadata", "output", "choices"]
39
+ if attr_name in predefined_attrs:
40
+ return super().__getattribute__(attr_name)
41
+ else:
42
+ output = self.output
43
+ if attr_name in output:
44
+ return output[attr_name]
45
+ else:
46
+ try:
47
+ return self.data[attr_name]
48
+ except AttributeError:
49
+ raise AttributeError(f"Attribute `{attr_name}` not found")
50
+
51
+ def to_dict(self) -> Dict[str, Any]:
52
+ """Convert all information within the data sample into a dict. Information generated
53
+ during the inference will be saved into output field.
54
+ """
55
+ from flashrag.dataset.utils import convert_numpy
56
+
57
+ output = {
58
+ "id": self.id,
59
+ "question": self.question,
60
+ "golden_answers": self.golden_answers,
61
+ "output": convert_numpy(self.output),
62
+ }
63
+ if self.metadata:
64
+ output["metadata"] = self.metadata
65
+
66
+ return output
67
+
68
+ def __str__(self) -> str:
69
+ """Return a string representation of the item with its main attributes."""
70
+ return json.dumps(self.to_dict(), indent=4)
71
+
72
+
73
+ class Dataset:
74
+ """A container class used to store the whole dataset. Inside the class, each data sample will be stored
75
+ in `Item` class. The properties of the dataset represent the list of attributes corresponding to each item in the dataset.
76
+ """
77
+
78
+ def __init__(
79
+ self,
80
+ config: Optional[Dict[str, Any]] = None,
81
+ dataset_path: Optional[str] = None,
82
+ data: Optional[List[Dict[str, Any]]] = None,
83
+ sample_num: Optional[int] = None,
84
+ random_sample: bool = False,
85
+ ) -> None:
86
+ if config is not None:
87
+ self.config = config
88
+ dataset_name = config['dataset_name'] if 'dataset_name' in config else 'defalut_dataset'
89
+ else:
90
+ self.config = None
91
+ warnings.warn("dataset_name is not in config, set it as default.")
92
+ dataset_name = "default_dataset"
93
+ self.dataset_name = dataset_name
94
+ self.dataset_path = dataset_path
95
+
96
+ self.sample_num = sample_num
97
+ self.random_sample = random_sample
98
+
99
+ if data is None:
100
+ self.data = self._load_data(self.dataset_name, self.dataset_path)
101
+ else:
102
+ print("Load data from provided data")
103
+ assert isinstance(data[0], dict)
104
+ self.data = [Item(item_dict) for item_dict in data]
105
+
106
+ def _load_data(self, dataset_name: str, dataset_path: str) -> List[Item]:
107
+ """Load data from the provided dataset_path or directly download the file(TODO)."""
108
+ if not os.path.exists(dataset_path):
109
+ # TODO: auto download: self._download(self.dataset_name, dataset_path)
110
+ raise FileNotFoundError(f"Dataset file {dataset_path} not found.")
111
+
112
+ data = []
113
+ with open(dataset_path, "r", encoding="utf-8") as f:
114
+ for line in f:
115
+ item_dict = json.loads(line)
116
+ item = Item(item_dict)
117
+ data.append(item)
118
+ if self.sample_num is not None:
119
+ if self.random_sample:
120
+ print(f"Random sample {self.sample_num} items in test set.")
121
+ data = random.sample(data, self.sample_num)
122
+ else:
123
+ data = data[: self.sample_num]
124
+
125
+ return data
126
+
127
+ def update_output(self, key: str, value_list: List[Any]) -> None:
128
+ """Update the overall output field for each sample in the dataset."""
129
+ assert len(self.data) == len(value_list)
130
+ for item, value in zip(self.data, value_list):
131
+ item.update_output(key, value)
132
+
133
+ @property
134
+ def question(self) -> List[Optional[str]]:
135
+ return [item.question for item in self.data]
136
+
137
+ @property
138
+ def golden_answers(self) -> List[List[str]]:
139
+ return [item.golden_answers for item in self.data]
140
+
141
+ @property
142
+ def id(self) -> List[Optional[str]]:
143
+ return [item.id for item in self.data]
144
+
145
+ @property
146
+ def output(self) -> List[Dict[str, Any]]:
147
+ return [item.output for item in self.data]
148
+
149
+ def get_batch_data(self, attr_name: str, batch_size: int) -> Generator[List[Any], None, None]:
150
+ """Get an attribute of dataset items in batch."""
151
+ for i in range(0, len(self.data), batch_size):
152
+ batch_items = self.data[i : i + batch_size]
153
+ yield [item[attr_name] for item in batch_items]
154
+
155
+ def __getattr__(self, attr_name: str) -> List[Any]:
156
+ return [item.__getattr__(attr_name) for item in self.data]
157
+
158
+ def get_attr_data(self, attr_name: str) -> List[Any]:
159
+ """For the attributes constructed later (not implemented using property),
160
+ obtain a list of this attribute in the entire dataset.
161
+ """
162
+ return [item[attr_name] for item in self.data]
163
+
164
+ def __getitem__(self, index: int) -> Item:
165
+ return self.data[index]
166
+
167
+ def __len__(self) -> int:
168
+ return len(self.data)
169
+
170
+ def save(self, save_path: str) -> None:
171
+ """Save the dataset into the original format."""
172
+
173
+ save_data = [item.to_dict() for item in self.data]
174
+
175
+ with open(save_path, "w", encoding="utf-8") as f:
176
+ json.dump(save_data, f, indent=4)
177
+
178
+ def __str__(self) -> str:
179
+ """Return a string representation of the dataset with a summary of items."""
180
+ return f"Dataset '{self.dataset_name}' with {len(self)} items"
@@ -1,6 +1,22 @@
1
+ from typing import Dict, Any, Union
2
+ import numpy as np
1
3
  from flashrag.dataset import Dataset
2
4
 
3
5
 
6
+ def convert_numpy(obj: Union[Dict, list, np.ndarray, np.generic]) -> Any:
7
+ """Recursively convert numpy objects in nested dictionaries or lists to native Python types."""
8
+ if isinstance(obj, dict):
9
+ return {k: convert_numpy(v) for k, v in obj.items()}
10
+ elif isinstance(obj, list):
11
+ return [convert_numpy(i) for i in obj]
12
+ elif isinstance(obj, np.ndarray):
13
+ return obj.tolist() # Convert numpy arrays to lists
14
+ elif isinstance(obj, (np.integer, np.floating)):
15
+ return obj.item() # Convert numpy scalars to native Python scalars
16
+ else:
17
+ return obj # Return the object as-is if it's neither a dict, list, nor numpy type
18
+
19
+
4
20
  def filter_dataset(dataset: Dataset, filter_func=None):
5
21
  if filter_func is None:
6
22
  return dataset
@@ -17,28 +33,20 @@ def split_dataset(dataset: Dataset, split_symbol: list):
17
33
  data = dataset.data
18
34
  data_split = {symbol: [] for symbol in set(split_symbol)}
19
35
  for symbol in set(split_symbol):
20
- symbol_data = [
21
- x for x, x_symbol in zip(data, split_symbol) if x_symbol == symbol
22
- ]
36
+ symbol_data = [x for x, x_symbol in zip(data, split_symbol) if x_symbol == symbol]
23
37
  data_split[symbol] = Dataset(config=dataset.config, data=symbol_data)
24
38
 
25
39
  return data_split
26
40
 
27
41
 
28
42
  def merge_dataset(dataset_split: dict, split_symbol: list):
29
- assert len(split_symbol) == sum(
30
- [len(data) for data in dataset_split.values()]
31
- )
32
- dataset_split_iter = {
33
- symbol: iter(dataset.data) for symbol, dataset in dataset_split.items()
34
- }
43
+ assert len(split_symbol) == sum([len(data) for data in dataset_split.values()])
44
+ dataset_split_iter = {symbol: iter(dataset.data) for symbol, dataset in dataset_split.items()}
35
45
 
36
46
  final_data = []
37
47
  for item_symbol in split_symbol:
38
48
  final_data.append(next(dataset_split_iter[item_symbol]))
39
- final_dataset = Dataset(
40
- config=list(dataset_split.values())[0].config, data=final_data
41
- )
49
+ final_dataset = Dataset(config=list(dataset_split.values())[0].config, data=final_data)
42
50
 
43
51
  return final_dataset
44
52
 
@@ -0,0 +1,3 @@
1
+ from flashrag.generator.generator import *
2
+ from flashrag.generator.openai_generator import *
3
+ from flashrag.generator.utils import *
@@ -1,5 +1,6 @@
1
1
  from typing import List
2
2
  from copy import deepcopy
3
+ import warnings
3
4
  from tqdm import tqdm
4
5
  from tqdm.auto import trange
5
6
  import numpy as np
@@ -11,6 +12,7 @@ from transformers import (
11
12
  BartForConditionalGeneration,
12
13
  AutoConfig,
13
14
  )
15
+ from flashrag.generator.utils import resolve_max_tokens
14
16
 
15
17
 
16
18
  class BaseGenerator:
@@ -53,15 +55,11 @@ class EncoderDecoderGenerator(BaseGenerator):
53
55
 
54
56
  self.model = FiDT5.from_pretrained(self.model_path)
55
57
  else:
56
- self.model = T5ForConditionalGeneration.from_pretrained(
57
- self.model_path
58
- )
58
+ self.model = T5ForConditionalGeneration.from_pretrained(self.model_path)
59
59
  else:
60
60
  if self.fid:
61
61
  assert False, "FiD only support T5"
62
- self.model = BartForConditionalGeneration.from_pretrained(
63
- self.model_path
64
- )
62
+ self.model = BartForConditionalGeneration.from_pretrained(self.model_path)
65
63
  self.model.cuda()
66
64
  self.model.eval()
67
65
  self.tokenizer = AutoTokenizer.from_pretrained(self.model_path)
@@ -108,27 +106,14 @@ class EncoderDecoderGenerator(BaseGenerator):
108
106
  ]
109
107
  generation_params["stopping_criteria"] = stopping_criteria
110
108
 
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)
109
+ generation_params = resolve_max_tokens(params, generation_params, prioritize_new_tokens=True)
121
110
 
122
111
  responses = []
123
- for idx in trange(
124
- 0, len(input_list), batch_size, desc="Generation process: "
125
- ):
112
+ for idx in trange(0, len(input_list), batch_size, desc="Generation process: "):
126
113
  batched_prompts = input_list[idx : idx + batch_size]
127
114
  if self.fid:
128
115
  # assume each input in input_list is a list, contains K string
129
- input_ids, attention_mask = self.encode_passages(
130
- batched_prompts
131
- )
116
+ input_ids, attention_mask = self.encode_passages(batched_prompts)
132
117
  inputs = {
133
118
  "input_ids": input_ids.to(self.device),
134
119
  "attention_mask": attention_mask.to(self.device),
@@ -173,11 +158,7 @@ class VLLMGenerator(BaseGenerator):
173
158
  else:
174
159
  tensor_parallel_size = self.gpu_num
175
160
 
176
- self.lora_path = (
177
- None
178
- if "generator_lora_path" not in config
179
- else config["generator_lora_path"]
180
- )
161
+ self.lora_path = None if "generator_lora_path" not in config else config["generator_lora_path"]
181
162
  self.use_lora = False
182
163
  if self.lora_path is not None:
183
164
  self.use_lora = True
@@ -197,9 +178,7 @@ class VLLMGenerator(BaseGenerator):
197
178
  gpu_memory_utilization=gpu_memory_utilization,
198
179
  max_logprobs=32016,
199
180
  )
200
- self.tokenizer = AutoTokenizer.from_pretrained(
201
- self.model_path, trust_remote_code=True
202
- )
181
+ self.tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
203
182
 
204
183
  @torch.inference_mode(mode=True)
205
184
  def generate(
@@ -219,23 +198,16 @@ class VLLMGenerator(BaseGenerator):
219
198
  if "do_sample" in generation_params:
220
199
  do_sample_flag = generation_params.pop("do_sample")
221
200
  if not do_sample_flag:
222
- generation_params['temperature'] = 0
223
- generation_params['seed'] = self.config['seed']
224
- max_tokens = params.pop("max_tokens", None) or params.pop(
225
- "max_new_tokens", None
226
- )
227
- if max_tokens is not None:
228
- generation_params["max_tokens"] = max_tokens
229
- else:
230
- generation_params["max_tokens"] = generation_params.get(
231
- "max_tokens", generation_params.pop("max_new_tokens", None)
232
- )
233
- generation_params.pop("max_new_tokens", None)
201
+ generation_params["temperature"] = 0
202
+ generation_params["seed"] = self.config["seed"]
203
+
204
+ # handle param conflict
205
+ generation_params = resolve_max_tokens(params, generation_params, prioritize_new_tokens=False)
234
206
 
235
207
  # fix for llama3
236
208
  if "stop" in generation_params:
237
209
  generation_params["stop"].append("<|eot_id|>")
238
- generation_params['include_stop_str_in_output'] = True
210
+ generation_params["include_stop_str_in_output"] = True
239
211
  else:
240
212
  generation_params["stop"] = ["<|eot_id|>"]
241
213
 
@@ -265,12 +237,7 @@ class VLLMGenerator(BaseGenerator):
265
237
  scores = []
266
238
  for output in outputs:
267
239
  logprobs = output.outputs[0].logprobs
268
- scores.append(
269
- [
270
- np.exp(list(score_dict.values())[0].logprob)
271
- for score_dict in logprobs
272
- ]
273
- )
240
+ scores.append([np.exp(list(score_dict.values())[0].logprob) for score_dict in logprobs])
274
241
  return base_output, scores
275
242
  else:
276
243
  return base_output
@@ -282,11 +249,7 @@ class HFCausalLMGenerator(BaseGenerator):
282
249
  def __init__(self, config, model=None):
283
250
  super().__init__(config)
284
251
  self.config = config
285
- lora_path = (
286
- None
287
- if "generator_lora_path" not in config
288
- else config["generator_lora_path"]
289
- )
252
+ lora_path = None if "generator_lora_path" not in config else config["generator_lora_path"]
290
253
  self.model, self.tokenizer = self._load_model(model=model)
291
254
  self.use_lora = False
292
255
  if lora_path is not None:
@@ -305,28 +268,24 @@ class HFCausalLMGenerator(BaseGenerator):
305
268
  else:
306
269
  model.cuda()
307
270
  model.eval()
308
- tokenizer = AutoTokenizer.from_pretrained(
309
- self.model_path, trust_remote_code=True
310
- )
271
+ tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
311
272
  if "qwen" not in self.model_name:
312
273
  tokenizer.pad_token = tokenizer.eos_token
313
274
  tokenizer.padding_side = "left"
314
275
 
315
276
  return model, tokenizer
316
277
 
317
- def add_new_tokens(
318
- self, token_embedding_path, token_name_func=lambda idx: f"[ref{idx+1}]"
319
- ):
278
+ def add_new_tokens(self, token_embedding_path, token_name_func=lambda idx: f"[ref{idx+1}]"):
320
279
  del self.model
321
280
  self.model = AutoModelForCausalLM.from_pretrained(
322
- self.model_path,
323
- trust_remote_code=True,
281
+ self.model_path,
282
+ trust_remote_code=True,
324
283
  )
325
284
  # get original embedding weight matrix
326
285
  embedding_layer = self.model.get_input_embeddings()
327
286
  embedding_weights = embedding_layer.weight
328
287
  original_vocab_size, embedding_dim = embedding_weights.shape
329
-
288
+
330
289
  new_tokens_weights = torch.load(token_embedding_path)
331
290
  new_tokens_length = new_tokens_weights.shape[0]
332
291
 
@@ -386,16 +345,7 @@ class HFCausalLMGenerator(BaseGenerator):
386
345
  ]
387
346
  generation_params["stopping_criteria"] = stopping_criteria
388
347
 
389
- max_tokens = params.pop("max_tokens", None) or params.pop(
390
- "max_new_tokens", None
391
- )
392
- if max_tokens is not None:
393
- generation_params["max_new_tokens"] = max_tokens
394
- else:
395
- generation_params["max_new_tokens"] = generation_params.get(
396
- "max_new_tokens", generation_params.pop("max_tokens", None)
397
- )
398
- generation_params.pop("max_tokens", None)
348
+ generation_params = resolve_max_tokens(params, generation_params, prioritize_new_tokens=True)
399
349
 
400
350
  # set eos token for llama
401
351
  if "llama" in self.model_name.lower():
@@ -413,9 +363,7 @@ class HFCausalLMGenerator(BaseGenerator):
413
363
  generated_token_ids = []
414
364
  generated_token_logits = []
415
365
 
416
- for idx in trange(
417
- 0, len(input_list), batch_size, desc="Generation process: "
418
- ):
366
+ for idx in trange(0, len(input_list), batch_size, desc="Generation process: "):
419
367
  torch.cuda.empty_cache()
420
368
  batched_prompts = input_list[idx : idx + batch_size]
421
369
  inputs = self.tokenizer(
@@ -435,12 +383,7 @@ class HFCausalLMGenerator(BaseGenerator):
435
383
  generated_ids = outputs.sequences
436
384
  logits = torch.stack(outputs.scores, dim=1).softmax(-1)
437
385
  generated_ids = generated_ids[:, inputs["input_ids"].shape[-1] :]
438
- gen_score = (
439
- torch.gather(logits, 2, generated_ids[:, :, None])
440
- .squeeze(-1)
441
- .cpu()
442
- .tolist()
443
- )
386
+ gen_score = torch.gather(logits, 2, generated_ids[:, :, None]).squeeze(-1).cpu().tolist()
444
387
  scores.extend(gen_score)
445
388
 
446
389
  # get additinoal info
@@ -448,26 +391,15 @@ class HFCausalLMGenerator(BaseGenerator):
448
391
  batch_generated_token_ids = generated_ids.detach().cpu()
449
392
  batch_generated_token_logits = (
450
393
  torch.cat(
451
- [
452
- token_scores.unsqueeze(1)
453
- for token_scores in outputs.scores
454
- ],
394
+ [token_scores.unsqueeze(1) for token_scores in outputs.scores],
455
395
  dim=1,
456
396
  )
457
397
  .detach()
458
398
  .cpu()
459
399
  )
460
- if (
461
- batch_generated_token_ids.shape[1]
462
- < generation_params["max_new_tokens"]
463
- ):
464
- real_batch_size, num_generated_tokens = (
465
- batch_generated_token_ids.shape
466
- )
467
- padding_length = (
468
- generation_params["max_new_tokens"]
469
- - num_generated_tokens
470
- )
400
+ if batch_generated_token_ids.shape[1] < generation_params["max_new_tokens"]:
401
+ real_batch_size, num_generated_tokens = batch_generated_token_ids.shape
402
+ padding_length = generation_params["max_new_tokens"] - num_generated_tokens
471
403
  padding_token_ids = torch.zeros(
472
404
  (real_batch_size, padding_length),
473
405
  dtype=batch_generated_token_ids.dtype,
@@ -480,9 +412,7 @@ class HFCausalLMGenerator(BaseGenerator):
480
412
  ),
481
413
  dtype=batch_generated_token_logits.dtype,
482
414
  )
483
- batch_generated_token_ids = torch.cat(
484
- [batch_generated_token_ids, padding_token_ids], dim=1
485
- )
415
+ batch_generated_token_ids = torch.cat([batch_generated_token_ids, padding_token_ids], dim=1)
486
416
  batch_generated_token_logits = torch.cat(
487
417
  [batch_generated_token_logits, padding_token_logits],
488
418
  dim=1,
@@ -569,11 +499,7 @@ class FastChatGenerator(HFCausalLMGenerator):
569
499
  def get_gpu_memory(max_gpus=None):
570
500
  """Get available memory for each GPU."""
571
501
  gpu_memory = []
572
- num_gpus = (
573
- torch.cuda.device_count()
574
- if max_gpus is None
575
- else min(max_gpus, torch.cuda.device_count())
576
- )
502
+ num_gpus = torch.cuda.device_count() if max_gpus is None else min(max_gpus, torch.cuda.device_count())
577
503
  for gpu_id in range(num_gpus):
578
504
  with torch.cuda.device(gpu_id):
579
505
  device = torch.cuda.current_device()
@@ -594,10 +520,7 @@ class FastChatGenerator(HFCausalLMGenerator):
594
520
  max_gpu_memory = None
595
521
  if self.gpu_num != 1:
596
522
  available_gpu_memory = get_gpu_memory(self.gpu_num)
597
- max_gpu_memory = (
598
- str(int(min(available_gpu_memory) * gpu_memory_utilization))
599
- + "GiB"
600
- )
523
+ max_gpu_memory = str(int(min(available_gpu_memory) * gpu_memory_utilization)) + "GiB"
601
524
 
602
525
  model, tokenizer = load_model(
603
526
  self.model_path,
@@ -611,14 +534,10 @@ class FastChatGenerator(HFCausalLMGenerator):
611
534
 
612
535
  else:
613
536
  model.cuda()
614
- tokenizer = AutoTokenizer.from_pretrained(
615
- self.model_path, trust_remote_code=True
616
- )
537
+ tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
617
538
  model.eval()
618
539
 
619
- tokenizer = AutoTokenizer.from_pretrained(
620
- self.model_path, trust_remote_code=True
621
- )
540
+ tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
622
541
  if "qwen" not in self.model_name:
623
542
  tokenizer.pad_token = tokenizer.eos_token
624
543
  tokenizer.padding_side = "left"
@@ -0,0 +1,67 @@
1
+ import warnings
2
+
3
+
4
+ def resolve_max_tokens(params: dict, generation_params: dict, prioritize_new_tokens: bool = False) -> dict:
5
+ """
6
+ Resolve and validate max_tokens parameters from both params and generation_params.
7
+
8
+ Args:
9
+ params: Dictionary containing user-provided parameters
10
+ generation_params: Dictionary containing generation-specific parameters
11
+ prioritize_new_tokens: If True, max_new_tokens takes precedence over max_tokens
12
+ If False, max_tokens takes precedence (default behavior)
13
+
14
+ Returns:
15
+ Updated generation_params dictionary
16
+ """
17
+
18
+ def get_token_params(param_dict: dict) -> tuple:
19
+ """Extract max_tokens and max_new_tokens from a parameter dictionary."""
20
+ return (param_dict.pop("max_tokens", None), param_dict.pop("max_new_tokens", None))
21
+
22
+ def resolve_tokens(max_tokens: int, max_new_tokens: int) -> int:
23
+ """
24
+ Resolve between max_tokens and max_new_tokens values based on priority.
25
+ Returns the resolved token value or None if no valid value found.
26
+ """
27
+ # If either value is None, return the non-None value
28
+ if max_tokens is None:
29
+ return max_new_tokens
30
+ if max_new_tokens is None:
31
+ return max_tokens
32
+
33
+ # Both values exist but are different
34
+ if max_tokens != max_new_tokens:
35
+ if prioritize_new_tokens:
36
+ warnings.warn(
37
+ f"max_tokens ({max_tokens}) and max_new_tokens ({max_new_tokens}) "
38
+ f"are different. Using max_new_tokens value as it has priority."
39
+ )
40
+ return max_new_tokens
41
+ else:
42
+ warnings.warn(
43
+ f"max_tokens ({max_tokens}) and max_new_tokens ({max_new_tokens}) "
44
+ f"are different. Using max_tokens value as it has priority."
45
+ )
46
+ return max_tokens
47
+
48
+ # Both values are equal
49
+ return max_tokens
50
+
51
+ # Try to resolve from params first, then fall back to generation_params
52
+ max_tokens, max_new_tokens = get_token_params(params)
53
+ final_max_tokens = resolve_tokens(max_tokens, max_new_tokens)
54
+
55
+ # If no valid tokens found in params, try generation_params
56
+ if final_max_tokens is None:
57
+ max_tokens, max_new_tokens = get_token_params(generation_params)
58
+ final_max_tokens = resolve_tokens(max_tokens, max_new_tokens)
59
+
60
+ generation_params.pop("max_new_tokens", None)
61
+ generation_params.pop("max_tokens", None)
62
+ if final_max_tokens is not None:
63
+ if prioritize_new_tokens:
64
+ generation_params["max_new_tokens"] = final_max_tokens
65
+ else:
66
+ generation_params["max_tokens"] = final_max_tokens
67
+ return generation_params
@@ -5,6 +5,22 @@ from flashrag.retriever.utils import load_model, pooling, parse_query
5
5
 
6
6
 
7
7
  class Encoder:
8
+ """
9
+ Encoder class for encoding queries using a specified model.
10
+
11
+ Attributes:
12
+ model_name (str): The name of the model.
13
+ model_path (str): The path to the model.
14
+ pooling_method (str): The method used for pooling.
15
+ max_length (int): The maximum length of the input sequences.
16
+ use_fp16 (bool): Whether to use FP16 precision.
17
+ instruction (str): Additional instructions for parsing queries.
18
+
19
+ Methods:
20
+ encode(query_list: List[str], is_query=True) -> np.ndarray:
21
+ Encodes a list of queries into embeddings.
22
+ """
23
+
8
24
  def __init__(self, model_name, model_path, pooling_method, max_length, use_fp16, instruction):
9
25
  self.model_name = model_name
10
26
  self.model_path = model_path
@@ -15,7 +31,7 @@ class Encoder:
15
31
 
16
32
  self.model, self.tokenizer = load_model(model_path=model_path, use_fp16=use_fp16)
17
33
 
18
- @torch.inference_mode(mode=True)
34
+ @torch.inference_mode()
19
35
  def encode(self, query_list: List[str], is_query=True) -> np.ndarray:
20
36
  query_list = parse_query(self.model_name, query_list, self.instruction)
21
37
 
@@ -44,6 +60,23 @@ class Encoder:
44
60
 
45
61
 
46
62
  class STEncoder:
63
+ """
64
+ STEncoder class for encoding queries using SentenceTransformers.
65
+
66
+ Attributes:
67
+ model_name (str): The name of the model.
68
+ model_path (str): The path to the model.
69
+ max_length (int): The maximum length of the input sequences.
70
+ use_fp16 (bool): Whether to use FP16 precision.
71
+ instruction (str): Additional instructions for parsing queries.
72
+
73
+ Methods:
74
+ encode(query_list: List[str], batch_size=64, is_query=True) -> np.ndarray:
75
+ Encodes a list of queries into embeddings.
76
+ multi_gpu_encode(query_list: List[str], is_query=True, batch_size=None) -> np.ndarray:
77
+ Encodes a list of queries into embeddings using multiple GPUs.
78
+ """
79
+
47
80
  def __init__(self, model_name, model_path, max_length, use_fp16, instruction):
48
81
  import torch
49
82
  from sentence_transformers import SentenceTransformer
@@ -54,10 +87,10 @@ class STEncoder:
54
87
  self.use_fp16 = use_fp16
55
88
  self.instruction = instruction
56
89
  self.model = SentenceTransformer(
57
- model_path, model_kwargs={"torch_dtype": torch.float16 if use_fp16 else torch.float}
90
+ model_path, trust_remote_code=True, model_kwargs={"torch_dtype": torch.float16 if use_fp16 else torch.float}
58
91
  )
59
92
 
60
- @torch.inference_mode(mode=True)
93
+ @torch.inference_mode()
61
94
  def encode(self, query_list: List[str], batch_size=64, is_query=True) -> np.ndarray:
62
95
  query_list = parse_query(self.model_name, query_list, self.instruction)
63
96
  query_emb = self.model.encode(
@@ -67,14 +100,19 @@ class STEncoder:
67
100
 
68
101
  return query_emb
69
102
 
70
- @torch.inference_mode(mode=True)
103
+ @torch.inference_mode()
71
104
  def multi_gpu_encode(self, query_list: List[str], is_query=True, batch_size=None) -> np.ndarray:
72
105
  query_list = parse_query(self.model_name, query_list, self.instruction)
73
106
  pool = self.model.start_multi_process_pool()
74
107
  query_emb = self.model.encode_multi_process(
75
- query_list, pool, convert_to_numpy=True, normalize_embeddings=True, batch_size=batch_size,show_progress_bar=True
108
+ query_list,
109
+ pool,
110
+ convert_to_numpy=True,
111
+ normalize_embeddings=True,
112
+ batch_size=batch_size,
113
+ show_progress_bar=True,
76
114
  )
77
115
  self.model.stop_multi_process_pool(pool)
78
- query_emb.astype(np.float32, order="C")
116
+ query_emb = query_emb.astype(np.float32, order="C")
79
117
 
80
118
  return query_emb
@@ -0,0 +1 @@
1
+ __version__ = "0.1.3dev20241111"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flashrag-dev
3
- Version: 0.1.3.dev20241108
3
+ Version: 0.1.3.dev20241111
4
4
  Summary: A library for efficient Retrieval-Augmented Generation research
5
5
  Home-page: https://github.com/RUC-NLPIR/FlashRAG
6
6
  Author: Jiajie Jin, Yutao Zhu, Chenghao Zhang, Xinyu Yang, Zhicheng Dou
@@ -20,6 +20,7 @@ flashrag/generator/fid.py
20
20
  flashrag/generator/generator.py
21
21
  flashrag/generator/openai_generator.py
22
22
  flashrag/generator/stop_word_criteria.py
23
+ flashrag/generator/utils.py
23
24
  flashrag/judger/__init__.py
24
25
  flashrag/judger/judger.py
25
26
  flashrag/pipeline/__init__.py
@@ -1,160 +0,0 @@
1
- import os
2
- import json
3
- import random
4
- import numpy as np
5
-
6
-
7
- class Item:
8
- r"""A container class used to store and manipulate a sample within a dataset.
9
- Information related to this sample during training/inference will be stored in ```self.output```.
10
- Each attribute of this class can be used like a dict key(also for key in ```self.output```).
11
-
12
- """
13
-
14
- def __init__(self, item_dict):
15
- self.id = item_dict.get("id", None)
16
- self.question = item_dict.get("question", None)
17
- self.golden_answers = item_dict.get("golden_answers", [])
18
- self.choices = item_dict.get("choices", [])
19
- self.metadata = item_dict.get("metadata", {})
20
- self.output = item_dict.get("output", {})
21
-
22
- def update_output(self, key, value):
23
- r"""Update the output dict and keep a key in self.output can be used as an attribute."""
24
- if key in ["id", "question", "golden_answers", "output"]:
25
- raise AttributeError(f"{key} should not be changed")
26
- else:
27
- self.output[key] = value
28
-
29
- def update_evaluation_score(self, metric_name, metric_score):
30
- r"""Update the evaluation score of this sample for a metric."""
31
- if "metric_score" not in self.output:
32
- self.output["metric_score"] = {}
33
- self.output["metric_score"][metric_name] = metric_score
34
-
35
- def __getattr__(self, attr_name):
36
- if attr_name in ["id", "question", "golden_answers", "metadata", "output", "choices"]:
37
- return super().__getattribute__(attr_name)
38
- else:
39
- output = super().__getattribute__("output")
40
- if attr_name in output:
41
- return output[attr_name]
42
- else:
43
- raise AttributeError(f"Attribute `{attr_name}` not found")
44
-
45
- def to_dict(self):
46
- r"""Convert all information within the data sample into a dict. Information generated
47
- during the inference will be saved into output field.
48
-
49
- """
50
- for k, v in self.output.items():
51
- if isinstance(k, np.ndarray):
52
- self.output[k] = v.tolist()
53
- output = {
54
- "id": self.id,
55
- "question": self.question,
56
- "golden_answers": self.golden_answers,
57
- "output": self.output,
58
- }
59
- if self.metadata != {}:
60
- output["metadata"] = self.metadata
61
-
62
- return output
63
-
64
-
65
- class Dataset:
66
- """A container class used to store the whole dataset. Inside the class, each data sample will be stored
67
- in ```Item``` class.
68
- The properties of the dataset represent the list of attributes corresponding to each item in the dataset.
69
- """
70
-
71
- def __init__(self, config=None, dataset_path=None, data=None, sample_num=None, random_sample=False):
72
- self.config = config
73
- self.dataset_name = config["dataset_name"]
74
- self.dataset_path = dataset_path
75
-
76
- self.sample_num = sample_num
77
- self.random_sample = random_sample
78
-
79
- if data is None:
80
- self.data = self._load_data(self.dataset_name, self.dataset_path)
81
- else:
82
- self.data = data
83
-
84
- def _load_data(self, dataset_name, dataset_path):
85
- """Load data from the provided dataset_path or directly download the file(TODO)."""
86
-
87
- if not os.path.exists(dataset_path):
88
- # TODO: auto download: self._download(dataset_name, dataset_path)
89
- pass
90
-
91
- data = []
92
- with open(dataset_path, "r", encoding="utf-8") as f:
93
- for line in f:
94
- item_dict = json.loads(line)
95
- item = Item(item_dict)
96
- data.append(item)
97
- if self.sample_num is not None:
98
- if self.random_sample:
99
- print(f"Random sample {self.sample_num} items in test set.")
100
- data = random.sample(data, self.sample_num)
101
- else:
102
- data = data[: self.sample_num]
103
-
104
- return data
105
-
106
- def update_output(self, key, value_list):
107
- """Update the overall output field for each sample in the dataset."""
108
-
109
- assert len(self.data) == len(value_list)
110
- for item, value in zip(self.data, value_list):
111
- item.update_output(key, value)
112
-
113
- @property
114
- def question(self):
115
- return [item.question for item in self.data]
116
-
117
- @property
118
- def golden_answers(self):
119
- return [item.golden_answers for item in self.data]
120
-
121
- @property
122
- def id(self):
123
- return [item.id for item in self.data]
124
-
125
- @property
126
- def output(self):
127
- return [item.output for item in self.data]
128
-
129
- def get_batch_data(self, attr_name: str, batch_size: int):
130
- """Get an attribute of dataset items in batch."""
131
-
132
- for i in range(0, len(self.data), batch_size):
133
- batch_items = self.data[i : i + batch_size]
134
- yield [item[attr_name] for item in batch_items]
135
-
136
- def __getattr__(self, attr_name):
137
- return [item.__getattr__(attr_name) for item in self.data]
138
-
139
- def get_attr_data(self, attr_name):
140
- """For the attributes constructed later (not implemented using property),
141
- obtain a list of this attribute in the entire dataset.
142
- """
143
- return [item[attr_name] for item in self.data]
144
-
145
- def __getitem__(self, index):
146
- return self.data[index]
147
-
148
- def __len__(self):
149
- return len(self.data)
150
-
151
- def save(self, save_path):
152
- """Save the dataset into the original format."""
153
-
154
- def convert_to_float(d):
155
- return {k: (v.item() if isinstance(v, np.generic) else v) for k, v in d.items()}
156
-
157
- save_data = [convert_to_float(item.to_dict()) for item in self.data]
158
-
159
- with open(save_path, "w") as f:
160
- json.dump(save_data, f, indent=4)
@@ -1,2 +0,0 @@
1
- from flashrag.generator.generator import *
2
- from flashrag.generator.openai_generator import *
@@ -1 +0,0 @@
1
- __version__ = "0.1.3dev20241108"