explodinggradients / ragas

Evaluation framework for your Retrieval Augmented Generation (RAG) pipelines
https://docs.ragas.io
Apache License 2.0
5.66k stars 528 forks source link

LangchainLLMWrapper - no attribute agenerate_prompt - Unable to use HuggingFace LLMs and embedding models for test set generation. #1065

Open netopia-gab opened 3 days ago

netopia-gab commented 3 days ago

[ /] I have checked the documentation and related resources and couldn't resolve my bug.

Describe the bug I'm currently trying to use HuggingFace LLMs and embedding models for RAGAS test set generation instead of using OpenAI's ChatGPT to save costs. In doing so, I encountered an error that indicates a missing attribute in LangchainLLMWrapper.

Ragas version: 0.1.10 Python version: 3.9.18

Code to Reproduce import torch from ragas.llms import LangchainLLMWrapper from ragas.testset.generator import TestsetGenerator from langchain_huggingface import HuggingFacePipeline from ragas.embeddings import LangchainEmbeddingsWrapper from langchain_community.embeddings import HuggingFaceBgeEmbeddings from ragas.testset.evolutions import simple, reasoning, multi_context from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, pipeline

bnb_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16) # bits and bytes for model quantization

model_config = AutoTokenizer.from_pretrained("microsoft/Orca-2-13b", token="...")

model = AutoModelForCausalLM.from_pretrained("microsoft/Orca-2-13b", device_map="auto", token="...", quantization_config=bnb_config)

generate_text = pipeline(model=model, tokenizer=model_config, return_full_text=True, task="text-generation")

langchain_embeddings = HuggingFaceBgeEmbeddings(model_name="BAAI/bge-large-en-v1.5", model_kwargs={'device': 'cuda'}, encode_kwargs={'normalize_embeddings': True})

langchain_llm = HuggingFacePipeline(pipeline=generate_text)

langchain_llm = LangchainLLMWrapper(langchain_llm) langchain_embeddings = LangchainEmbeddingsWrapper(langchain_embeddings)

from langchain_community.document_loaders import PubMedLoader

loader = PubMedLoader("liver", load_max_docs=10) documents = loader.load()

generator = TestsetGenerator.from_langchain( generator_llm=langchain_llm, critic_llm=langchain_llm, embeddings=langchain_embeddings, )

distributions = { simple: 0.5, multi_context: 0.4, reasoning: 0.1 }

print("checkpoint") testset = generator.generate_with_langchain_docs(documents, 1, distributions) print("checkpoint_2") test_df = testset.to_pandas() test_df.to_csv('test/testset_test.csv')

Error trace

Expected behavior Exception in thread Thread-3: Traceback (most recent call last): File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/threading.py", line 980, in _bootstrap_inner self.run() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 87, in run results = self.loop.run_until_complete(self._aresults()) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete return future.result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 79, in _aresults r = await future File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/asyncio/tasks.py", line 611, in _wait_for_one return f.result() # May raise f.exception(). File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 37, in sema_coro return await coro File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 109, in wrapped_callable_async raise e File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 104, in wrapped_callable_async result = await callable(*args, kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/extractor.py", line 49, in extract results = await self.llm.generate(prompt=prompt, is_async=is_async) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/llms/base.py", line 93, in generate return await agenerate_text_with_retry( File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 88, in async_wrapped return await fn(*args, *kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 47, in call do = self.iter(retry_state=retry_state) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/init.py", line 325, in iter raise retry_exc.reraise() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/init.py", line 158, in reraise raise self.last_attempt.result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/concurrent/futures/_base.py", line 439, in result return self.__get_result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/concurrent/futures/_base.py", line 391, in get_result raise self._exception File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 50, in call__ result = await fn(args, kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/llms/base.py", line 178, in agenerate_text result = await self.langchain_llm.agenerate_prompt( AttributeError: 'LangchainLLMWrapper' object has no attribute 'agenerate_prompt' Traceback (most recent call last): File "/storage/local/mgmanzanillo3/projects/netopia/testset_generation/test.py", line 67, in testset = generator.generate_with_langchain_docs(documents, 1, distributions) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/generator.py", line 206, in generate_with_langchain_docs self.docstore.add_documents( File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/docstore.py", line 215, in add_documents self.add_nodes(nodes, show_progress=show_progress) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/docstore.py", line 254, in add_nodes raise ExceptionInRunner() ragas.exceptions.ExceptionInRunner: The runner thread which was running the jobs raised an exeception. Read the traceback above to debug it. You can also pass raise_exceptions=False incase you want to show only a warning message instead.

Additional context None

dosubot[bot] commented 3 days ago

Hey there, @netopia-gab! 👋 I'm here to help you with any bugs, questions, or even becoming a contributor. Let's squash those bugs together!

To resolve the AttributeError: 'LangchainLLMWrapper' object has no attribute 'agenerate_prompt', you need to ensure that the LangchainLLMWrapper class is correctly calling the agenerate method of the langchain_llm object. The error suggests that the langchain_llm object does not have an agenerate_prompt method.

Here is the corrected code for the LangchainLLMWrapper class:

class LangchainLLMWrapper(BaseRagasLLM):
    """
    A simple base class for RagasLLMs that is based on Langchain's BaseLanguageModel
    interface. it implements 2 functions:
    - generate_text: for generating text from a given PromptValue
    - agenerate_text: for generating text from a given PromptValue asynchronously
    """

    def __init__(
        self, langchain_llm: BaseLanguageModel, run_config: t.Optional[RunConfig] = None
    ):
        self.langchain_llm = langchain_llm
        if run_config is None:
            run_config = RunConfig()
        self.set_run_config(run_config)

    def generate_text(
        self,
        prompt: PromptValue,
        n: int = 1,
        temperature: float = 1e-8,
        stop: t.Optional[t.List[str]] = None,
        callbacks: Callbacks = None,
    ) -> LLMResult:
        temperature = self.get_temperature(n=n)
        if is_multiple_completion_supported(self.langchain_llm):
            return self.langchain_llm.generate(
                prompts=[prompt],
                n=n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
        else:
            result = self.langchain_llm.generate(
                prompts=[prompt] * n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
            # make LLMResult.generation appear as if it was n_completions
            # note that LLMResult.runs is still a list that represents each run
            generations = [[g[0] for g in result.generations]]
            result.generations = generations
            return result

    async def agenerate_text(
        self,
        prompt: PromptValue,
        n: int = 1,
        temperature: float = 1e-8,
        stop: t.Optional[t.List[str]] = None,
        callbacks: Callbacks = None,
    ) -> LLMResult:
        temperature = self.get_temperature(n=n)
        if is_multiple_completion_supported(self.langchain_llm):
            return await self.langchain_llm.agenerate(
                prompts=[prompt],
                n=n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
        else:
            result = await self.langchain_llm.agenerate(
                prompts=[prompt] * n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
            # make LLMResult.generation appear as if it was n_completions
            # note that LLMResult.runs is still a list that represents each run
            generations = [[g[0] for g in result.generations]]
            result.generations = generations
            return result

    def set_run_config(self, run_config: RunConfig):
        self.run_config = run_config

        # configure if using OpenAI API
        if isinstance(self.langchain_llm, BaseOpenAI) or isinstance(
            self.langchain_llm, ChatOpenAI
        ):
            try:
                from openai import RateLimitError
            except ImportError:
                raise ImportError(
                    "openai.error.RateLimitError not found. Please install openai package as `pip install openai`"
                )
            self.langchain_llm.request_timeout = run_config.timeout
            self.run_config.exception_types = RateLimitError

Make sure that the langchain_llm object has the generate and agenerate methods instead of generate_prompt and agenerate_prompt. This should resolve the AttributeError [1][2].

To continue talking to Dosu, mention @dosu.

netopia-gab commented 2 days ago

Implementing the previous code, I now have the this error.

Exception in thread Thread-3: Traceback (most recent call last): File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/threading.py", line 980, in _bootstrap_inner self.run() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 87, in run results = self.loop.run_until_complete(self._aresults()) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete return future.result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 79, in _aresults r = await future File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/asyncio/tasks.py", line 611, in _wait_for_one return f.result() # May raise f.exception(). File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 37, in sema_coro return await coro File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 109, in wrapped_callable_async raise e File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/executor.py", line 104, in wrapped_callable_async result = await callable(*args, kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/extractor.py", line 49, in extract results = await self.llm.generate(prompt=prompt, is_async=is_async) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/llms/base.py", line 93, in generate return await agenerate_text_with_retry( File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 88, in async_wrapped return await fn(*args, *kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 47, in call do = self.iter(retry_state=retry_state) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/init.py", line 325, in iter raise retry_exc.reraise() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/init.py", line 158, in reraise raise self.last_attempt.result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/concurrent/futures/_base.py", line 439, in result return self.__get_result() File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/concurrent/futures/_base.py", line 391, in get_result raise self._exception File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/tenacity/_asyncio.py", line 50, in call__ result = await fn(args, kwargs) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/llms/base.py", line 178, in agenerate_text result = await self.langchain_llm.agenerate( AttributeError: 'LangchainLLMWrapper' object has no attribute 'agenerate' Traceback (most recent call last): File "/storage/local/mgmanzanillo3/projects/netopia/testset_generation/test.py", line 53, in testset = generator.generate_with_langchain_docs(documents, 1, distributions) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/generator.py", line 206, in generate_with_langchain_docs self.docstore.add_documents( File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/docstore.py", line 215, in add_documents self.add_nodes(nodes, show_progress=show_progress) File "/home/mgmanzanillo3/miniconda3/envs/des_v2/lib/python3.9/site-packages/ragas/testset/docstore.py", line 254, in add_nodes raise ExceptionInRunner() ragas.exceptions.ExceptionInRunner: The runner thread which was running the jobs raised an exeception. Read the traceback above to debug it. You can also pass raise_exceptions=False incase you want to show only a warning message instead.

dosubot[bot] commented 2 days ago

To resolve the AttributeError: 'LangchainLLMWrapper' object has no attribute 'agenerate', you need to ensure that the LangchainLLMWrapper class is correctly calling the agenerate_text method. The LangchainLLMWrapper class should have an agenerate_text method, not agenerate.

Here is the corrected code for the LangchainLLMWrapper class:

class LangchainLLMWrapper(BaseRagasLLM):
    """
    A simple base class for RagasLLMs that is based on Langchain's BaseLanguageModel
    interface. it implements 2 functions:
    - generate_text: for generating text from a given PromptValue
    - agenerate_text: for generating text from a given PromptValue asynchronously
    """

    def __init__(
        self, langchain_llm: BaseLanguageModel, run_config: t.Optional[RunConfig] = None
    ):
        self.langchain_llm = langchain_llm
        if run_config is None:
            run_config = RunConfig()
        self.set_run_config(run_config)

    def generate_text(
        self,
        prompt: PromptValue,
        n: int = 1,
        temperature: float = 1e-8,
        stop: t.Optional[t.List[str]] = None,
        callbacks: Callbacks = None,
    ) -> LLMResult:
        temperature = self.get_temperature(n=n)
        if is_multiple_completion_supported(self.langchain_llm):
            return self.langchain_llm.generate(
                prompts=[prompt],
                n=n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
        else:
            result = self.langchain_llm.generate(
                prompts=[prompt] * n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
            generations = [[g[0] for g in result.generations]]
            result.generations = generations
            return result

    async def agenerate_text(
        self,
        prompt: PromptValue,
        n: int = 1,
        temperature: float = 1e-8,
        stop: t.Optional[t.List[str]] = None,
        callbacks: Callbacks = None,
    ) -> LLMResult:
        temperature = self.get_temperature(n=n)
        if is_multiple_completion_supported(self.langchain_llm):
            return await self.langchain_llm.agenerate(
                prompts=[prompt],
                n=n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
        else:
            result = await self.langchain_llm.agenerate(
                prompts=[prompt] * n,
                temperature=temperature,
                stop=stop,
                callbacks=callbacks,
            )
            generations = [[g[0] for g in result.generations]]
            result.generations = generations
            return result

    def set_run_config(self, run_config: RunConfig):
        self.run_config = run_config

        if isinstance(self.langchain_llm, BaseOpenAI) or isinstance(
            self.langchain_llm, ChatOpenAI
        ):
            try:
                from openai import RateLimitError
            except ImportError:
                raise ImportError(
                    "openai.error.RateLimitError not found. Please install openai package as `pip install openai`"
                )
            self.langchain_llm.request_timeout = run_config.timeout
            self.run_config.exception_types = RateLimitError

Make sure that the langchain_llm object has the agenerate method. If it does not, you may need to update your Langchain library or ensure that the correct class is being used. This should resolve the AttributeError [1].

To continue talking to Dosu, mention @dosu.