langgenius / dify

Dify is an open-source LLM app development platform. Dify's intuitive interface combines AI workflow, RAG pipeline, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production.
https://dify.ai
Other
50.36k stars 7.22k forks source link

embedding error #7701

Closed imaxwen closed 2 months ago

imaxwen commented 2 months ago

Self Checks

Dify version

0.7.2

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

Create Knowledge and upload a simple excel file, there goes an error below(using TONGYI's text-embedding-v2):

worker-1      | Traceback (most recent call last):
worker-1      |   File "/app/api/core/indexing_runner.py", line 77, in run
worker-1      |     self._load(
worker-1      |   File "/app/api/core/indexing_runner.py", line 694, in _load
worker-1      |     tokens += future.result()
worker-1      |   File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 451, in result
worker-1      |     return self.__get_result()
worker-1      |   File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
worker-1      |     raise self._exception
worker-1      |   File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
worker-1      |     result = self.fn(*self.args, **self.kwargs)
worker-1      |   File "/app/api/core/indexing_runner.py", line 749, in _process_chunk
worker-1      |     index_processor.load(dataset, chunk_documents, with_keywords=False)
worker-1      |   File "/app/api/core/rag/index_processor/processor/paragraph_index_processor.py", line 60, in load
worker-1      |     vector.create(documents)
worker-1      |   File "/app/api/core/rag/datasource/vdb/vector_factory.py", line 100, in create
worker-1      |     embeddings = self._embeddings.embed_documents([document.page_content for document in texts])
worker-1      |   File "/app/api/core/embedding/cached_embedding.py", line 82, in embed_documents
worker-1      |     raise ex
worker-1      |   File "/app/api/core/embedding/cached_embedding.py", line 51, in embed_documents
worker-1      |     embedding_result = self._model_instance.invoke_text_embedding(
worker-1      |   File "/app/api/core/model_manager.py", line 172, in invoke_text_embedding
worker-1      |     return self._round_robin_invoke(
worker-1      |   File "/app/api/core/model_manager.py", line 303, in _round_robin_invoke
worker-1      |     return function(*args, **kwargs)
worker-1      |   File "/app/api/core/model_runtime/model_providers/__base/text_embedding_model.py", line 38, in invoke
worker-1      |     raise self._transform_invoke_error(e)
worker-1      | core.model_runtime.errors.invoke.InvokeError: [tongyi] Error: 'NoneType' object is not subscriptable

✔️ Expected Behavior

No response

❌ Actual Behavior

No response

dosubot[bot] commented 2 months ago

@imaxwen Hello there! I'm here to help you with any bugs, questions, or contributions. Let me know how I can assist you while we wait for a human maintainer.

It looks like you're encountering a 'NoneType' object is not subscriptable error when using TONGYI's text-embedding-v2 in Dify version 0.7.2. This issue typically occurs when the response from the dashscope.TextEmbedding.call method does not contain the expected data.

To resolve this, you need to ensure that the response.output and response.usage are not None before attempting to subscript them. Here is a modified version of the embed_documents method with added checks to handle this scenario:

@staticmethod
def embed_documents(
    credentials_kwargs: dict, model: str, texts: list[str]
) -> tuple[list[list[float]], int]:
    """Call out to Tongyi's embedding endpoint.

    Args:
        credentials_kwargs: The credentials to use for the call.
        model: The model to use for embedding.
        texts: The list of texts to embed.

    Returns:
        List of embeddings, one for each text, and tokens usage.
    """
    embeddings = []
    embedding_used_tokens = 0
    for text in texts:
        response = dashscope.TextEmbedding.call(
            api_key=credentials_kwargs["dashscope_api_key"],
            model=model,
            input=text,
            text_type="document",
        )
        if response.output and "embeddings" in response.output and response.output["embeddings"]:
            data = response.output["embeddings"][0]
            if "embedding" in data:
                embeddings.append(data["embedding"])
            else:
                raise ValueError("Embedding data is missing in the response.")
        else:
            raise ValueError("Response output is missing or does not contain embeddings.")

        if response.usage and "total_tokens" in response.usage:
            embedding_used_tokens += response.usage["total_tokens"]
        else:
            raise ValueError("Response usage is missing or does not contain total tokens.")

    return [list(map(float, e)) for e in embeddings], embedding_used_tokens

This code adds checks to ensure that response.output and response.usage are not None and contain the expected keys before attempting to access them. If the expected data is missing, it raises a ValueError with an appropriate message [1][2].

To continue talking to Dosu, mention @dosu.