Skip to content

Commit a0bd4e7

Browse files
Merge pull request #5 from savitharaghunathan/ragas_embedding_issue
Support for embedding models for answer relevancy in ragas
2 parents 204abbb + 0013a75 commit a0bd4e7

1 file changed

Lines changed: 85 additions & 6 deletions

File tree

geneval/adapters/ragas_adapter.py

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import httpx
44
from typing import List, Dict, Any, Optional
5+
from langchain_openai import OpenAIEmbeddings
56
from ragas.metrics import (
67
LLMContextPrecisionWithoutReference,
78
LLMContextPrecisionWithReference,
@@ -69,16 +70,19 @@ def __init__(self, llm_manager: LLMManager):
6970

7071
# Initialize metrics with LLM configuration
7172
try:
73+
# Create embeddings wrapper for metrics that need it
74+
ragas_embeddings = self._create_ragas_embeddings_wrapper()
75+
7276
# For LLM-dependent metrics, we need to pass the LLM instance
7377
# RAGAS expects LLM instances to have certain methods
7478
self.available_metrics = {
7579
"context_precision_without_reference": LLMContextPrecisionWithoutReference(llm=self.llm),
7680
"context_precision_with_reference": LLMContextPrecisionWithReference(llm=self.llm),
7781
"context_recall": LLMContextRecall(llm=self.llm),
78-
"context_entity_recall": ContextEntityRecall(),
79-
"noise_sensitivity": NoiseSensitivity(),
80-
"answer_relevancy": AnswerRelevancy(),
81-
"faithfulness": Faithfulness()
82+
"context_entity_recall": ContextEntityRecall(llm=self.llm),
83+
"noise_sensitivity": NoiseSensitivity(llm=self.llm),
84+
"answer_relevancy": AnswerRelevancy(llm=self.llm, embeddings=ragas_embeddings) if ragas_embeddings else AnswerRelevancy(llm=self.llm),
85+
"faithfulness": Faithfulness(llm=self.llm)
8286
}
8387
self.logger.info(f"RAGAS metrics initialized successfully with {len(self.available_metrics)} metrics")
8488
except Exception as e:
@@ -376,6 +380,75 @@ def _create_vllm_provider(self, provider_name: str) -> Optional[ChatOpenAI]:
376380
self.logger.error(f"Error creating vLLM provider: {e}")
377381
return None
378382

383+
def _create_ragas_embeddings_wrapper(self):
384+
"""
385+
Create a RAGAS-compatible embeddings wrapper for metrics that require embeddings
386+
This supports custom OpenAI-compatible embedding endpoints for non-OpenAI models
387+
"""
388+
try:
389+
# Check for embedding-specific environment variables
390+
# These can be different from the main LLM configuration
391+
embedding_api_key = os.getenv("OPENAI_EMBEDDING_API_KEY")
392+
embedding_base_url = os.getenv("OPENAI_EMBEDDING_BASE_URL")
393+
embedding_model = os.getenv("OPENAI_EMBEDDING_MODEL", "text-embedding-ada-002")
394+
395+
# If no embedding-specific config, try to use the main OpenAI config
396+
if not embedding_api_key:
397+
# Check if we have OpenAI as a configured provider
398+
openai_config = self.llm_manager.get_provider_config("openai")
399+
if openai_config:
400+
api_key_env = openai_config.get("api_key_env", "OPENAI_API_KEY")
401+
embedding_api_key = os.getenv(api_key_env)
402+
if not embedding_base_url:
403+
# Use the same base URL as the main OpenAI config if available
404+
embedding_base_url = openai_config.get("base_url")
405+
406+
if not embedding_api_key:
407+
self.logger.warning("No embedding API key found. Answer relevancy may not work optimally.")
408+
return None
409+
410+
# Configure embeddings parameters
411+
embeddings_kwargs = {
412+
"model": embedding_model,
413+
"openai_api_key": embedding_api_key
414+
}
415+
416+
# Set custom base URL if provided
417+
if embedding_base_url and embedding_base_url != "https://api.openai.com/v1":
418+
embeddings_kwargs["openai_api_base"] = embedding_base_url
419+
self.logger.info(f"Using custom embeddings base URL: {embedding_base_url}")
420+
421+
# Handle SSL ignore setting
422+
openai_ignore_ssl = os.getenv("OPENAI_IGNORE_SSL", "false").lower() == "true"
423+
if openai_ignore_ssl:
424+
try:
425+
# Create HTTP clients with SSL verification disabled
426+
sync_http_client = httpx.Client(verify=False, timeout=30)
427+
async_http_client = httpx.AsyncClient(verify=False, timeout=30)
428+
429+
embeddings_kwargs["http_client"] = sync_http_client
430+
embeddings_kwargs["http_async_client"] = async_http_client
431+
432+
self.logger.info("Created RAGAS embeddings wrapper with SSL verification disabled")
433+
except Exception as ssl_error:
434+
self.logger.warning(f"Failed to configure SSL ignore for embeddings: {ssl_error}")
435+
else:
436+
self.logger.info("Created RAGAS embeddings wrapper with standard SSL")
437+
438+
# Create LangChain embeddings wrapper with configuration
439+
embeddings = OpenAIEmbeddings(**embeddings_kwargs)
440+
441+
self.logger.info(f"Embeddings configured successfully with model: {embedding_model}")
442+
if embedding_base_url:
443+
self.logger.info(f"Using custom endpoint: {embedding_base_url}")
444+
445+
return embeddings
446+
447+
except Exception as e:
448+
self.logger.error(f"Failed to create RAGAS embeddings wrapper: {e}")
449+
self.logger.warning("Answer relevancy metric will work with LLM only (may be less optimal)")
450+
return None
451+
379452
def _prepare_dataset(self, input: Input) -> Dataset:
380453
"""
381454
Convert input to RAGAS-compatible dataset format
@@ -390,7 +463,10 @@ def _prepare_dataset(self, input: Input) -> Dataset:
390463
"contexts": [contexts],
391464
"answer": [input.response],
392465
"ground_truths": [[input.reference]],
393-
"reference": [input.reference]
466+
"reference": [input.reference],
467+
# AnswerRelevancy specific columns
468+
"user_input": [input.question],
469+
"response": [input.response],
394470
}
395471
self.logger.info(f"Dataset prepared with context")
396472
return Dataset.from_dict(data)
@@ -429,7 +505,10 @@ def evaluate(self, input: Input) -> Output:
429505
"contexts": "contexts",
430506
"answer": "answer",
431507
"ground_truths": "ground_truths",
432-
"reference": "reference"
508+
"reference": "reference",
509+
# AnswerRelevancy specific mappings
510+
"user_input": "user_input",
511+
"response": "response",
433512
}
434513
)
435514

0 commit comments

Comments
 (0)