File size: 1,495 Bytes
bd46c34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from .base import AgentLike
from ..utils.parsing import extract_legal_moves, extract_forbidden, slice_board_and_moves, MOVE_RE
from ..prompts import get_prompt_pack

class HFLocalAgent(AgentLike):
  def __init__(self, model_id: str, prompt_pack: str="base", **gen):
    self.model_name = f"hf:{model_id}"
    self.pack = get_prompt_pack(prompt_pack)
    self.tok = AutoTokenizer.from_pretrained(model_id, use_fast=True)
    self.model = AutoModelForCausalLM.from_pretrained(
      model_id, torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
      device_map="auto"
    )
    self.gen = dict(max_new_tokens=32, do_sample=True, temperature=0.1, top_p=0.9, **gen)

  def __call__(self, observation: str) -> str:
    legal = extract_legal_moves(observation)
    if not legal: return ""
    forb = set(extract_forbidden(observation))
    legal_filtered = [m for m in legal if m not in forb] or legal

    sys = self.pack.system
    user = self.pack.guidance(slice_board_and_moves(observation))
    prompt = f"{sys}\n\n{user}"

    inputs = self.tok(prompt, return_tensors="pt").to(self.model.device)
    with torch.no_grad():
      out = self.model.generate(**inputs, **self.gen)
    text = self.tok.decode(out[0], skip_special_tokens=True)
    m = MOVE_RE.search(text[len(prompt):])
    return m.group(0) if m and m.group(0) in legal_filtered else legal_filtered[0]