Add optional sentence-boundary generation stop
Browse files- tiny_english/generate.py +12 -6
tiny_english/generate.py
CHANGED
|
@@ -49,10 +49,10 @@ def load_export(directory, device="cpu"):
|
|
| 49 |
return model.to(device=device, dtype=torch.bfloat16).eval(), tokenizer, metadata["checkpoint_step"]
|
| 50 |
|
| 51 |
|
| 52 |
-
def complete(model, tokenizer, prompt, max_new_tokens=150, temperature=0.8, top_k=40, seed=42, deadline=None, strict_context=False):
|
| 53 |
if not isinstance(prompt, str) or not prompt.strip():
|
| 54 |
raise ValueError("Prompt must not be empty")
|
| 55 |
-
if not math.isfinite(temperature) or temperature <= 0 or top_k < 1 or max_new_tokens < 1:
|
| 56 |
raise ValueError("Generation numeric options must be positive and finite")
|
| 57 |
tokens = tokenizer.encode(prompt).ids
|
| 58 |
prompt_tokens = len(tokens)
|
|
@@ -71,10 +71,16 @@ def complete(model, tokenizer, prompt, max_new_tokens=150, temperature=0.8, top_
|
|
| 71 |
logits = model(inputs)[0, -1].float() / temperature
|
| 72 |
values, indices = logits.topk(min(top_k, logits.numel()))
|
| 73 |
next_token = indices[torch.multinomial(values.softmax(-1), 1, generator=generator)].item()
|
| 74 |
-
if next_token == tokenizer.token_to_id("<eos>"):
|
| 75 |
-
finish_reason = "eos"
|
| 76 |
-
break
|
| 77 |
-
tokens.append(next_token)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
return {
|
| 79 |
"text": tokenizer.decode(tokens),
|
| 80 |
"completion": tokenizer.decode(tokens[prompt_tokens:]),
|
|
|
|
| 49 |
return model.to(device=device, dtype=torch.bfloat16).eval(), tokenizer, metadata["checkpoint_step"]
|
| 50 |
|
| 51 |
|
| 52 |
+
def complete(model, tokenizer, prompt, max_new_tokens=150, temperature=0.8, top_k=40, seed=42, deadline=None, strict_context=False, stop_at_sentence_end=False, min_new_tokens=0):
|
| 53 |
if not isinstance(prompt, str) or not prompt.strip():
|
| 54 |
raise ValueError("Prompt must not be empty")
|
| 55 |
+
if not math.isfinite(temperature) or temperature <= 0 or top_k < 1 or max_new_tokens < 1 or min_new_tokens < 0:
|
| 56 |
raise ValueError("Generation numeric options must be positive and finite")
|
| 57 |
tokens = tokenizer.encode(prompt).ids
|
| 58 |
prompt_tokens = len(tokens)
|
|
|
|
| 71 |
logits = model(inputs)[0, -1].float() / temperature
|
| 72 |
values, indices = logits.topk(min(top_k, logits.numel()))
|
| 73 |
next_token = indices[torch.multinomial(values.softmax(-1), 1, generator=generator)].item()
|
| 74 |
+
if next_token == tokenizer.token_to_id("<eos>"):
|
| 75 |
+
finish_reason = "eos"
|
| 76 |
+
break
|
| 77 |
+
tokens.append(next_token)
|
| 78 |
+
if stop_at_sentence_end and len(tokens) - prompt_tokens >= min_new_tokens:
|
| 79 |
+
ending = tokenizer.decode([next_token]).rstrip()
|
| 80 |
+
completion = tokenizer.decode(tokens[prompt_tokens:])
|
| 81 |
+
if ending.endswith((".", "!", "?")) and completion.count('"') % 2 == 0:
|
| 82 |
+
finish_reason = "sentence"
|
| 83 |
+
break
|
| 84 |
return {
|
| 85 |
"text": tokenizer.decode(tokens),
|
| 86 |
"completion": tokenizer.decode(tokens[prompt_tokens:]),
|