danielfein's picture
Add training support package
a4019dd verified
Raw
History Blame Contribute Delete
5.58 kB
from __future__ import annotations
import json
from dataclasses import asdict
from pathlib import Path
import torch
from .checkpoints import load_token_checkpoint
from .config import PipelineConfig, VerbalizationTokenSetConfig
from .modeling import ModelBundle
def apply_token_pair(bundle: ModelBundle, token_dir: Path) -> None:
input_emb = bundle.model.get_input_embeddings()
ai_ckpt = load_token_checkpoint(token_dir / "ai_token.pt")
human_ckpt = load_token_checkpoint(token_dir / "human_token.pt")
ai_id = bundle.tokenizer.convert_tokens_to_ids(bundle.config.model.ai_token)
human_id = bundle.tokenizer.convert_tokens_to_ids(bundle.config.model.human_token)
with torch.no_grad():
input_emb.weight[ai_id].copy_(ai_ckpt.embedding.to(input_emb.weight.device, dtype=input_emb.weight.dtype))
input_emb.weight[human_id].copy_(
human_ckpt.embedding.to(input_emb.weight.device, dtype=input_emb.weight.dtype)
)
@torch.inference_mode()
def sample_text(
bundle: ModelBundle,
prompt: str,
*,
max_new_tokens: int,
do_sample: bool,
temperature: float,
top_p: float,
) -> str:
input_ids = bundle.tokenizer(prompt, return_tensors="pt", add_special_tokens=False)["input_ids"].to(
bundle.model.device
)
output = bundle.model.generate(
input_ids=input_ids,
max_new_tokens=max_new_tokens,
do_sample=do_sample,
temperature=temperature,
top_p=top_p,
pad_token_id=bundle.tokenizer.eos_token_id,
)
return bundle.tokenizer.decode(output[0, input_ids.shape[1] :], skip_special_tokens=True).strip()
def _chat_prompt(bundle: ModelBundle, content: str) -> str:
return bundle.tokenizer.apply_chat_template(
[{"role": "user", "content": content}],
tokenize=False,
add_generation_prompt=True,
)
@torch.inference_mode()
def verbalize_token(bundle: ModelBundle, token: str, *, max_new_tokens: int, do_sample: bool) -> str:
prompt = _chat_prompt(bundle, f"Describe what qualities of text would be implied by {token}.")
prompt += f"{token} text typically describes text that"
return sample_text(
bundle,
prompt,
max_new_tokens=max_new_tokens,
do_sample=do_sample,
temperature=1.0,
top_p=0.95 if do_sample else 1.0,
)
@torch.inference_mode()
def verbalize_difference(bundle: ModelBundle, *, max_new_tokens: int, do_sample: bool) -> str:
ai_token = bundle.config.model.ai_token
human_token = bundle.config.model.human_token
prompt = _chat_prompt(
bundle,
(
f"What is the difference between {ai_token} text and {human_token} text? "
f"Refer to {ai_token} text as A-type text and {human_token} text as B-type text. "
"Do not discuss the literal token strings; describe the passage qualities they accompany."
),
)
prompt += (
f"{ai_token}, which I will refer to as A-type text, and {human_token}, "
"B-type text, have many similarities and differences."
)
return sample_text(
bundle,
prompt,
max_new_tokens=max_new_tokens,
do_sample=do_sample,
temperature=1.0,
top_p=0.95 if do_sample else 1.0,
)
def verbalize_token_set(
bundle: ModelBundle,
token_set: VerbalizationTokenSetConfig,
config: PipelineConfig,
) -> dict:
apply_token_pair(bundle, token_set.token_dir)
payload = {
"name": token_set.name,
"token_dir": str(token_set.token_dir),
"model_name": config.model.model_name,
"ai_token": config.model.ai_token,
"human_token": config.model.human_token,
"greedy": {
"ai": verbalize_token(
bundle,
config.model.ai_token,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=False,
),
"human": verbalize_token(
bundle,
config.model.human_token,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=False,
),
"difference": verbalize_difference(
bundle,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=False,
),
},
"samples": [],
}
for _ in range(config.verbalization.n_samples):
payload["samples"].append(
{
"ai": verbalize_token(
bundle,
config.model.ai_token,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=True,
),
"human": verbalize_token(
bundle,
config.model.human_token,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=True,
),
"difference": verbalize_difference(
bundle,
max_new_tokens=config.verbalization.max_new_tokens,
do_sample=True,
),
}
)
return payload
def save_verbalizations(output_dir: Path, results: list[dict]) -> None:
output_dir.mkdir(parents=True, exist_ok=True)
(output_dir / "verbalizations.json").write_text(json.dumps(results, indent=2), encoding="utf-8")
for result in results:
(output_dir / f"{result['name']}.json").write_text(json.dumps(result, indent=2), encoding="utf-8")