This reverts commitabeadc49c8. Restores vendor/litellm-pgvector/ and the vector_store_registry wiring (in-band file_search tool-call support) at the user's request, after re-confirming against docs.litellm.ai/docs/completion/knowledgebase and litellm-pgvector's own README that pg_vector is still not an in-process vector_store_registry backend -- it requires this same standalone connector service either way, so there is no simpler 'native' path that was missed. Trading back in: 793 lines of vendored code, the untested Prisma migration, and the git-context build risk noted in VENDORED.md (all flagged as unverified against real hardware in issue #24), in exchange for the file_search in-band tool call memory-retrieval did not support. Conflicts resolved on top of later commits (Redis, update.sh key-minting fold-in): - .env.example / docs/memory-knowledgebase.md: kept the auto-mint-via- update.sh language, renamed MEMORY_RETRIEVAL_* back to LITELLM_PGVECTOR_*. - scripts/generate-secrets.sh: left deleted -- its job was folded into update.sh in24d749b, unrelated to this revert. - scripts/update.sh: renamed the MEMORY_RETRIEVAL_* secret/mint calls to LITELLM_PGVECTOR_* to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WHfjWrSEcGhCoeu6dQfDa
90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
from typing import List, Optional
|
|
from config import settings, EmbeddingConfig
|
|
from litellm.types.utils import EmbeddingResponse
|
|
import litellm
|
|
import logging
|
|
|
|
class EmbeddingService:
|
|
"""Service for generating embeddings using OpenAI SDK pointed at LiteLLM proxy"""
|
|
|
|
def __init__(self, config: Optional[EmbeddingConfig] = None):
|
|
self.config = config or settings.embedding
|
|
|
|
|
|
|
|
async def generate_embedding(self, text: str) -> List[float]:
|
|
"""
|
|
Generate embedding for a single text using LiteLLM proxy
|
|
|
|
Args:
|
|
text: Text to embed
|
|
|
|
Returns:
|
|
List of floats representing the embedding vector
|
|
"""
|
|
try:
|
|
response: EmbeddingResponse = await litellm.aembedding(
|
|
model=self.config.model,
|
|
input=[text],
|
|
api_base=self.config.base_url,
|
|
api_key=self.config.api_key
|
|
)
|
|
logging.debug(f"Embedding response: {response}")
|
|
|
|
# Extract embedding from response
|
|
embedding = response.data[0]["embedding"]
|
|
|
|
# Validate embedding dimensions
|
|
if len(embedding) != self.config.dimensions:
|
|
raise ValueError(
|
|
f"Expected embedding dimension {self.config.dimensions}, "
|
|
f"got {len(embedding)}"
|
|
)
|
|
|
|
return embedding
|
|
|
|
except Exception as e:
|
|
raise RuntimeError(f"Failed to generate embedding: {str(e)}")
|
|
|
|
async def generate_embeddings(self, texts: List[str]) -> List[List[float]]:
|
|
"""
|
|
Generate embeddings for multiple texts
|
|
|
|
Args:
|
|
texts: List of texts to embed
|
|
|
|
Returns:
|
|
List of embedding vectors
|
|
"""
|
|
try:
|
|
# Generate embeddings using LiteLLM
|
|
response = await litellm.aembedding(
|
|
model=self.config.model,
|
|
input=texts,
|
|
api_base=self.config.base_url,
|
|
api_key=self.config.api_key
|
|
)
|
|
|
|
# Extract embeddings from response
|
|
embeddings = [item.embedding for item in response.data]
|
|
|
|
# Validate embedding dimensions
|
|
for i, embedding in enumerate(embeddings):
|
|
if len(embedding) != self.config.dimensions:
|
|
raise ValueError(
|
|
f"Expected embedding dimension {self.config.dimensions} for text {i}, "
|
|
f"got {len(embedding)}"
|
|
)
|
|
|
|
return embeddings
|
|
|
|
except Exception as e:
|
|
raise RuntimeError(f"Failed to generate embeddings: {str(e)}")
|
|
|
|
def update_config(self, new_config: EmbeddingConfig):
|
|
"""Update the embedding configuration"""
|
|
self.config = new_config
|
|
|
|
|
|
# Global embedding service instance
|
|
embedding_service = EmbeddingService() |