| 173 | |
| 174 | |
| 175 | class CachingLM: |
| 176 | def __init__(self, lm, cache_db) -> None: |
| 177 | """LM wrapper that returns cached results if they exist, and uses the underlying LM if not. |
| 178 | |
| 179 | :param lm: LM |
| 180 | Underlying LM |
| 181 | :param cache_db: str |
| 182 | Path to cache db |
| 183 | """ |
| 184 | self.lm = lm |
| 185 | self.cache_db = cache_db |
| 186 | if os.path.dirname(cache_db): |
| 187 | os.makedirs(os.path.dirname(cache_db), exist_ok=True) |
| 188 | self.dbdict = SqliteDict(cache_db, autocommit=True) |
| 189 | |
| 190 | # add hook to lm |
| 191 | lm.set_cache_hook(self.get_cache_hook()) |
| 192 | |
| 193 | def __getattr__(self, attr): |
| 194 | lm_attr = getattr(self.lm, attr) |
| 195 | if not callable(lm_attr): |
| 196 | return lm_attr |
| 197 | |
| 198 | def fn(requests): |
| 199 | res = [] |
| 200 | remaining_reqs = [] |
| 201 | warned = False |
| 202 | # figure out which ones are cached and which ones are new |
| 203 | eval_logger.info( |
| 204 | f"Loading '{attr}' responses from cache '{self.cache_db}' where possible..." |
| 205 | ) |
| 206 | for req in tqdm(requests): |
| 207 | hsh = hash_args(attr, req.args) |
| 208 | if attr == "generate_until" and req.args[1].get("do_sample", False): |
| 209 | # when we are doing non-greedy generation, don't use the cache |
| 210 | # (else every "randomly sampled" generation would be identical for repeats > 1). |
| 211 | if not warned: |
| 212 | eval_logger.warning( |
| 213 | f"Arguments to lm.generate_until() '{req.args[1]}' include non-deterministic sampling. Caching will not be performed for such requests." |
| 214 | ) |
| 215 | warned = True |
| 216 | res.append(None) |
| 217 | remaining_reqs.append(req) |
| 218 | elif hsh in self.dbdict: |
| 219 | ob = self.dbdict[hsh] |
| 220 | |
| 221 | assert ob is not None |
| 222 | |
| 223 | res.append(ob) |
| 224 | else: |
| 225 | res.append(None) |
| 226 | remaining_reqs.append(req) |
| 227 | |
| 228 | # actually run the LM on the requests that do not have cached results |
| 229 | rem_res = getattr(self.lm, attr)(remaining_reqs) |
| 230 | |
| 231 | # stick the new ones back into the list and also cache any of the new ones |
| 232 | resptr = 0 |
nothing calls this directly
no outgoing calls
no test coverage detected