CodeGen / src /generators /program_generator.py
geekydraco's picture
Upload 41 files
27a6b62 verified
Raw History Blame Contribute Delete
2.67 kB
import logging
import torch
import os
os.environ.setdefault("PYTORCH_ENABLE_MPS_FALLBACK", "1")
from typing import Any
logger = logging.getLogger(__name__)
class GenerationPipeline:
def __init__(self, model: Any, tokenizer: Any, config: Any = None):
self.model = model
self.tokenizer = tokenizer
self.config = config
def _build_generation_kwargs(self) -> dict:
"""Builds generation kwargs based on config or defaults."""
# Safely extract token IDs as standard Python ints to prevent PyTorch warnings
eos_id = self.tokenizer.eos_token_id
if isinstance(eos_id, torch.Tensor):
eos_id = eos_id.item()
kwargs = {
"max_new_tokens": 128, # Hard cap: MongoDB queries are short
"temperature": 0.2,
"top_p": 0.95,
"top_k": 50,
"do_sample": True,
"pad_token_id": eos_id,
"eos_token_id": eos_id,
"repetition_penalty": 1.2,
"no_repeat_ngram_size": 3, # CRITICAL: Prevents repeating blocks of numbers/text
}
if self.config:
kwargs["max_new_tokens"] = min(getattr(self.config, "max_length", 256), 128)
kwargs["temperature"] = getattr(self.config, "temperature", 0.2)
kwargs["top_p"] = getattr(self.config, "top_p", 0.95)
kwargs["top_k"] = getattr(self.config, "top_k", 50)
return kwargs
def generate(self, prompt: str) -> str:
"""Generates text from a given prompt."""
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
with torch.no_grad():
outputs = self.model.generate(**inputs, **self._build_generation_kwargs())
generated_text = self.tokenizer.decode(
outputs[0][inputs["input_ids"].shape[1]:],
skip_special_tokens=True
)
generated_text = generated_text.strip()
generated_text = self._clean_output(generated_text)
return generated_text
@staticmethod
def _clean_output(text: str) -> str:
"""Remove hallucinated refusals or trailing junk after the actual answer."""
# Common patterns that indicate the model went off-track
stop_patterns = [
"I'm sorry", "I can't", "I cannot", "I am sorry",
"I apologize", "As an AI", "As a language model",
"```", "\n\n", "###", "Human:", "User:", "Assistant:"
]
for pattern in stop_patterns:
idx = text.find(pattern)
if idx > 0: # Only cut if it's not at the very start
text = text[:idx]
return text.strip()