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
45.3k stars 6.36k forks source link

After upgrade to latest docker image 0.7.0, Answer Node cannot reply files #7294

Closed cherry0411 closed 3 weeks ago

cherry0411 commented 4 weeks ago

Self Checks

Dify version

0.7.0

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

A HTTP Node accept image URL which send GET request download the image as files output variable, then an Answer Node reference files variable, to write image to response, then I got this error: Node (Image Response) run failed: 'FileVar' object has no attribute 'markdown'.

Before I upgrade to latest version, should be 0.6.7, is working normally.

issues_1

issues_2

✔️ Expected Behavior

Answer Node should process files variable correctly, as previous version did.

❌ Actual Behavior

Node (Image Response) run failed: 'FileVar' object has no attribute 'markdown'.

dosubot[bot] commented 4 weeks ago

@cherry0411 Hello there! I'm here to help you with bug fixes, answer questions, and even guide you on becoming a contributor. Let's squash those bugs together! 🤖

To resolve the issue where the Answer Node in your self-hosted Docker setup cannot reply with files after upgrading to version 0.7.0, you need to ensure that the FileVar class has a method to_markdown.

Here is an example of how you can implement this method:

class FileVar(BaseModel):
    id: Optional[str] = None  # message file id
    tenant_id: str
    type: FileType
    transfer_method: FileTransferMethod
    url: Optional[str] = None  # remote url
    related_id: Optional[str] = None
    extra_config: Optional[FileExtraConfig] = None
    filename: Optional[str] = None
    extension: Optional[str] = None
    mime_type: Optional[str] = None

    def to_dict(self) -> dict:
        return {
            '__variant': self.__class__.__name__,
            'tenant_id': self.tenant_id,
            'type': self.type.value,
            'transfer_method': self.transfer_method.value,
            'url': self.preview_url,
            'remote_url': self.url,
            'related_id': self.related_id,
            'filename': self.filename,
            'extension': self.extension,
            'mime_type': self.mime_type,
        }

    def to_markdown(self) -> str:
        """
        Convert file to markdown
        :return:
        """
        preview_url = self.preview_url
        if self.type == FileType.IMAGE:
            text = f'![{self.filename or ""}]({preview_url})'
        else:
            text = f'[{self.filename or preview_url}]({preview_url})'

        return text

    @property
    def data(self) -> Optional[str]:
        """
        Get image data, file signed url or base64 data
        depending on config MULTIMODAL_SEND_IMAGE_FORMAT
        :return:
        """
        return self._get_data()

    @property
    def preview_url(self) -> Optional[str]:
        """
        Get signed preview url
        :return:
        """
        return self._get_data(force_url=True)

    @property
    def prompt_message_content(self) -> ImagePromptMessageContent:
        if self.type == FileType.IMAGE:
            image_config = self.extra_config.image_config
            return ImagePromptMessageContent(
                data=self.data,
                detail=ImagePromptMessageContent.DETAIL.HIGH
                if image_config.get("detail") == "high" else ImagePromptMessageContent.DETAIL.LOW
            )

    def _get_data(self, force_url: bool = False) -> Optional[str]:
        from models.model import UploadFile
        if self.type == FileType.IMAGE:
            if self.transfer_method == FileTransferMethod.REMOTE_URL:
                return self.url
            elif self.transfer_method == FileTransferMethod.LOCAL_FILE:
                upload_file = (db.session.query(UploadFile)
                               .filter(
                    UploadFile.id == self.related_id,
                    UploadFile.tenant_id == self.tenant_id
                ).first())

                return UploadFileParser.get_image_data(
                    upload_file=upload_file,
                    force_url=force_url
                )
            elif self.transfer_method == FileTransferMethod.TOOL_FILE:
                extension = self.extension
                # add sign url
                return ToolFileParser.get_tool_file_manager().sign_file(tool_file_id=self.related_id, extension=extension)

        return None

This method converts the file to a markdown representation, which can then be used in the Answer Node to reply with files. Update the FileVar class in your codebase with this method, and the error should be resolved [1][2].

To continue talking to Dosu, mention @dosu.

crazywoola commented 4 weeks ago

Fixed in this PR https://github.com/langgenius/dify/pull/7293

cherry0411 commented 4 weeks ago

thanks, is there any plan for a hotfix release?

crazywoola commented 4 weeks ago

Not yet, I have just merged that PR. We will see later, I have pinned this issue, you can keep an eye on this.

141qq commented 4 weeks ago

stable diffusion也是同样问题 9437ff30-e647-470e-9854-85ac472ca904 image

crazywoola commented 3 weeks ago

Fixed in 0.7.1