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
51.47k stars 7.43k forks source link

Echarts that contains functions can't be rendered correctly on frontend. #8457

Closed fdb02983rhy closed 1 month ago

fdb02983rhy commented 1 month ago

Self Checks

Dify version

0.8.2

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

Output a echarts that contains any function in a markdown format on frontend.

{
    "tooltip": {
        "trigger": "item",
        "formatter": function(params) {
            return params.name + '<br/>Rainfall: ' + params.value[0] + ' mm<br/>Rainy Days: ' + params.value[1];
        }  👆👆👆
    },
    "xAxis": {
        "type": "value",
        "name": "Rainfall (mm)"
    },
    "yAxis": {
        "type": "value",
        "name": "Days with Rain"
    },
    "series": [
        {
            "type": "scatter",
            "symbolSize": function(data) {
                return (data[2] + 1) * 4;
            },
            "data": [
                [89.5, 12, 0],
                [65.2, 9, 1],
                [102.8, 15, 2],
                [78.3, 11, 3],
                [55.6, 8, 4],
                [30.2, 5, 5],
                [12.7, 3, 6],
                [8.9, 2, 7],
                [45.7, 7, 8],
                [87.4, 13, 9],
                [110.6, 16, 10],
                [95.1, 14, 11]
            ],
            "itemStyle": {
                "color": "#4169E1"
            }
        },
        {
            "type": "line",
            "showSymbol": false,
            "data": [[0, 0], [120, 18]],
            "lineStyle": {
                "color": "#FF4500",
                "type": "dashed"
            }
        }
    ],
    "dataZoom": [
        {
            "type": "inside",
            "start": 0,
            "end": 100
        },
        {
            "start": 0,
            "end": 100
        }
    ],
    "roam": true,
    "toolbox": {
        "feature": {
            "saveAsImage": {}
        }
    }
}

iScreen Shoter - 20240915092536911

After deleting the function:

{
    "tooltip": {
        "trigger": "item"
    },
    "xAxis": {
        "type": "value",
        "name": "Rainfall (mm)"
    },
    "yAxis": {
        "type": "value",
        "name": "Days with Rain"
    },
    "series": [
        {
            "type": "scatter",
            "data": [
                [89.5, 12, 0],
                [65.2, 9, 1],
                [102.8, 15, 2],
                [78.3, 11, 3],
                [55.6, 8, 4],
                [30.2, 5, 5],
                [12.7, 3, 6],
                [8.9, 2, 7],
                [45.7, 7, 8],
                [87.4, 13, 9],
                [110.6, 16, 10],
                [95.1, 14, 11]
            ],
            "itemStyle": {
                "color": "#4169E1"
            }
        },
        {
            "type": "line",
            "showSymbol": false,
            "data": [[0, 0], [120, 18]],
            "lineStyle": {
                "color": "#FF4500",
                "type": "dashed"
            }
        }
    ],
    "dataZoom": [
        {
            "type": "inside",
            "start": 0,
            "end": 100
        },
        {
            "start": 0,
            "end": 100
        }
    ],
    "roam": true,
    "toolbox": {
        "feature": {
            "saveAsImage": {}
        }
    }
}

iScreen Shoter - Google Chrome - 240915093138

✔️ Expected Behavior

Charts can be rendered, functions are supproted.

❌ Actual Behavior

Error displayed.

dosubot[bot] commented 1 month ago

Hello @fdb02983rhy! I'm here to help you with bugs, questions, and becoming a contributor. Let's work on this together!

The issue with Echarts containing functions not being rendered correctly on the frontend in version 0.8.2 of Dify when self-hosted with Docker is due to the fact that functions cannot be serialized and deserialized properly in JSON format, which is commonly used for data exchange in web applications.

To resolve this issue, you need to ensure that the chart configuration does not include functions or handle the functions separately in your code. Here is an example of how you might modify your chart configuration to avoid including functions directly:

import React from 'react';
import ReactECharts from 'echarts-for-react';

const getOption = () => ({
  tooltip: {
    trigger: 'item',
    formatter: (params) => `${params.name}<br/>Rainfall: ${params.value[0]} mm<br/>Rainy Days: ${params.value[1]}`
  },
  xAxis: {
    type: 'value',
    name: 'Rainfall (mm)'
  },
  yAxis: {
    type: 'value',
    name: 'Days with Rain'
  },
  series: [
    {
      type: 'scatter',
      symbolSize: (data) => (data[2] + 1) * 4,
      data: [
        [89.5, 12, 0],
        [65.2, 9, 1],
        [102.8, 15, 2],
        [78.3, 11, 3],
        [55.6, 8, 4],
        [30.2, 5, 5],
        [12.7, 3, 6],
        [8.9, 2, 7],
        [45.7, 7, 8],
        [87.4, 13, 9],
        [110.6, 16, 10],
        [95.1, 14, 11]
      ],
      itemStyle: {
        color: '#4169E1'
      }
    },
    {
      type: 'line',
      showSymbol: false,
      data: [[0, 0], [120, 18]],
      lineStyle: {
        color: '#FF4500',
        type: 'dashed'
      }
    }
  ],
  dataZoom: [
    {
      type: 'inside',
      start: 0,
      end: 100
    },
    {
      start: 0,
      end: 100
    }
  ],
  roam: true,
  toolbox: {
    feature: {
      saveAsImage: {}
    }
  }
});

const MyChart = () => {
  const option = getOption();
  return <ReactECharts option={option} />;
};

export default MyChart;

In this example, the getOption function is used to generate the chart configuration, ensuring that no functions are included directly in the configuration object. This way, the configuration can be safely serialized and deserialized without issues.

Additionally, the web/app/components/base/markdown.tsx file in Dify includes a CodeBlock component that handles ECharts JSON data. This component attempts to parse the JSON data and render the chart using ReactEcharts. If the JSON data is not in the correct format, it defaults to a simple error message chart. This approach ensures that the ECharts configuration is handled correctly and avoids issues with functions in the JSON data [1].

To continue talking to Dosu, mention @dosu.