from __future__ import annotations from typing import Iterable from app.core.config import settings try: import torch from transformers import AutoModel, AutoTokenizer except Exception: torch = None AutoModel = None AutoTokenizer = None class CodeEmbeddingService: def __init__(self) -> None: self._dim = settings.embedding_dim self._ready = False self._tokenizer = None self._model = None if AutoModel is not None and AutoTokenizer is not None: try: self._tokenizer = AutoTokenizer.from_pretrained(settings.codebert_model) self._model = AutoModel.from_pretrained(settings.codebert_model) self._model.eval() self._ready = True except Exception: self._ready = False @property def ready(self) -> bool: return self._ready @property def embedding_dim(self) -> int: return self._dim def embed_repository_signals(self, snippets: Iterable[str]) -> list[float]: text = "\n".join(snippets).strip() if not text: return [0.0] * self._dim if self._ready and torch is not None and self._tokenizer is not None and self._model is not None: tokens = self._tokenizer(text, return_tensors="pt", truncation=True, max_length=512) with torch.no_grad(): outputs = self._model(**tokens) cls = outputs.last_hidden_state[:, 0, :].squeeze(0) return cls.tolist() vector = [0.0] * self._dim for i, ch in enumerate(text): vector[i % self._dim] += (ord(ch) % 31) / 31.0 norm = sum(abs(v) for v in vector) or 1.0 return [v / norm for v in vector]