Spaces:
Runtime error
Runtime error
xiaofeifei
commited on
Commit
•
26bc264
1
Parent(s):
abb96f0
init commit
Browse files- .gitignore +5 -0
- LICENSE.txt +22 -0
- README.md +75 -0
- assets/bar.jpg +0 -0
- assets/line.jpg +0 -0
- assets/pie.png +0 -0
- assets/scatter.png +0 -0
- chart_gpt_app.py +73 -0
- prompts.py +71 -0
- requirements.txt +5 -0
- tools.py +78 -0
.gitignore
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.idea/
|
2 |
+
image/
|
3 |
+
llms/tk/
|
4 |
+
llms/ernie
|
5 |
+
__pycache__/
|
LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2023 Microsoft
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
22 |
+
|
README.md
CHANGED
@@ -9,5 +9,80 @@ app_file: app.py
|
|
9 |
pinned: false
|
10 |
license: mit
|
11 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
9 |
pinned: false
|
10 |
license: mit
|
11 |
---
|
12 |
+
# ChartGPT
|
13 |
+
ChartGPT allows data lake visualization as a graph through dialogue.
|
14 |
+
This project borrows some code from the [Viusal ChatGPT]( https://github.com/microsoft/TaskMatrix.git) project
|
15 |
+
|
16 |
+
## Effect Display
|
17 |
+
### 柱状图
|
18 |
+
![柱状图](./assets/bar.jpg)
|
19 |
+
|
20 |
+
### 折线图
|
21 |
+
![折线图](./assets/line.jpg)
|
22 |
+
|
23 |
+
### 饼图
|
24 |
+
![饼图](./assets/pie.png)
|
25 |
+
|
26 |
+
### 散点图
|
27 |
+
![饼图](./assets/scatter.png)
|
28 |
+
|
29 |
+
## 示例输入
|
30 |
+
```markdown
|
31 |
+
例一:
|
32 |
+
将[2,4,5,6,10,20,100]可视化为柱状图
|
33 |
+
|
34 |
+
例二:
|
35 |
+
将[2,4,5,6,10,100,120,200,135,50,10]可视化为折线图
|
36 |
+
|
37 |
+
例三:
|
38 |
+
将下面的数据可视化为饼图
|
39 |
+
['A', 'B', 'C', 'D', 'E']
|
40 |
+
[25, 20, 15, 10, 30]
|
41 |
+
|
42 |
+
例四
|
43 |
+
Visualize [2,4,5,6,10,100,120,200,135,50,10] as a line chart
|
44 |
+
|
45 |
+
例五:
|
46 |
+
将下面的数据可视化为散点图
|
47 |
+
x = [1, 2, 3, 4, 5]
|
48 |
+
y = [5, 4, 3, 2, 1]
|
49 |
+
|
50 |
+
```
|
51 |
+
|
52 |
+
## Quick Start
|
53 |
+
|
54 |
+
```shell
|
55 |
+
# clone the repo
|
56 |
+
git clone https://huggingface.co/spaces/xiaofeifei/ChartGPT
|
57 |
+
|
58 |
+
# Go to directory
|
59 |
+
cd ChartGPT
|
60 |
+
|
61 |
+
# create a new environment
|
62 |
+
conda create -n chartgpt python=3.8
|
63 |
+
|
64 |
+
# activate the new environment
|
65 |
+
conda activate chartgpt
|
66 |
+
|
67 |
+
# prepare the basic environments
|
68 |
+
pip install -r requirements.txt
|
69 |
+
|
70 |
+
# prepare your private OpenAI key (for Linux)
|
71 |
+
export OPENAI_API_KEY={Your_Private_Openai_Key}
|
72 |
+
|
73 |
+
# prepare your private OpenAI key (for Windows)
|
74 |
+
set OPENAI_API_KEY={Your_Private_Openai_Key}
|
75 |
+
|
76 |
+
# start!
|
77 |
+
python chart_gpt_app.py
|
78 |
+
```
|
79 |
+
|
80 |
+
|
81 |
+
## Acknowledgement
|
82 |
+
We appreciate the open source of the following projects:
|
83 |
+
[TaskMatrix]( https://github.com/microsoft/TaskMatrix.git)  
|
84 |
+
[LangChain](https://github.com/hwchase17/langchain)  
|
85 |
+
|
86 |
+
|
87 |
|
88 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
assets/bar.jpg
ADDED
assets/line.jpg
ADDED
assets/pie.png
ADDED
assets/scatter.png
ADDED
chart_gpt_app.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from prompts import *
|
2 |
+
from langchain.agents.initialize import initialize_agent
|
3 |
+
from langchain.chains.conversation.memory import ConversationBufferMemory
|
4 |
+
from langchain.llms.openai import OpenAI
|
5 |
+
import gradio as gr
|
6 |
+
import re
|
7 |
+
from tools import bar_tool, line_tool, pie_tool, scatter_tool
|
8 |
+
import os
|
9 |
+
|
10 |
+
|
11 |
+
class ConversationBot:
|
12 |
+
def __init__(self):
|
13 |
+
self.tools = [line_tool, bar_tool, pie_tool, scatter_tool]
|
14 |
+
print(f"All the Available Tools: {self.tools}")
|
15 |
+
self.memory = ConversationBufferMemory(memory_key="chat_history", output_key='output')
|
16 |
+
|
17 |
+
def init_agent(self, lang, openai_api_key):
|
18 |
+
self.memory.clear() # clear previous history
|
19 |
+
if lang == 'English':
|
20 |
+
PREFIX, FORMAT_INSTRUCTIONS, SUFFIX = CHARTGPT_PREFIX, CHARTGPT_FORMAT_INSTRUCTIONS, CHARTGPT_SUFFIX
|
21 |
+
place = "Enter text and press enter"
|
22 |
+
label_clear = "Clear"
|
23 |
+
else:
|
24 |
+
PREFIX, FORMAT_INSTRUCTIONS, SUFFIX = CHARTGPT_PREFIX_CN, CHARTGPT_FORMAT_INSTRUCTIONS_CN, CHARTGPT_SUFFIX_CN
|
25 |
+
place = "输入文字并回车"
|
26 |
+
label_clear = "清除"
|
27 |
+
os.environ["OPENAI_API_KEY"] = openai_api_key
|
28 |
+
self.llm = OpenAI()
|
29 |
+
self.agent = initialize_agent(
|
30 |
+
self.tools,
|
31 |
+
self.llm,
|
32 |
+
agent="conversational-react-description",
|
33 |
+
verbose=True,
|
34 |
+
memory=self.memory,
|
35 |
+
return_intermediate_steps=True,
|
36 |
+
agent_kwargs={'prefix': PREFIX, 'format_instructions': FORMAT_INSTRUCTIONS,
|
37 |
+
'suffix': SUFFIX}, )
|
38 |
+
print("init bot finished!")
|
39 |
+
return gr.update(visible=True), gr.update(visible=False), gr.update(placeholder=place), gr.update(
|
40 |
+
value=label_clear)
|
41 |
+
|
42 |
+
def run_text(self, text, state):
|
43 |
+
print(self.agent.memory)
|
44 |
+
res = self.agent({"input": text.strip()})
|
45 |
+
print("res:", res)
|
46 |
+
res['output'] = res['output'].replace("\\", "/")
|
47 |
+
response = re.sub('(image/[-\w]*.png)', lambda m: f'![](file={m.group(0)})*{m.group(0)}*', res['output'])
|
48 |
+
state = state + [(text, response)]
|
49 |
+
print(f"\nProcessed run_text, Input text: {text}\nCurrent state: {state}\n")
|
50 |
+
return state, state
|
51 |
+
|
52 |
+
|
53 |
+
if __name__ == '__main__':
|
54 |
+
bot = ConversationBot()
|
55 |
+
with gr.Blocks(css="#chatbot .overflow-y-auto{height:500px}") as demo:
|
56 |
+
openai_api_key = gr.Text(label="OPENAI_API_KEY")
|
57 |
+
lang = gr.Radio(choices=['Chinese', 'English'], value=None, label='Language')
|
58 |
+
chatbot = gr.Chatbot(elem_id="chatbot", label="ChartGPT")
|
59 |
+
state = gr.State([])
|
60 |
+
with gr.Row(visible=False) as input_raws:
|
61 |
+
with gr.Column(scale=0.7):
|
62 |
+
txt = gr.Textbox(show_label=False, placeholder="Enter text and press enter, or upload an image").style(
|
63 |
+
container=False)
|
64 |
+
with gr.Column(scale=0.15, min_width=0):
|
65 |
+
clear = gr.Button("Clear")
|
66 |
+
|
67 |
+
lang.change(bot.init_agent, [lang, openai_api_key], [input_raws, lang, txt, clear])
|
68 |
+
txt.submit(bot.run_text, [txt, state], [chatbot, state])
|
69 |
+
txt.submit(lambda: "", None, txt)
|
70 |
+
clear.click(bot.memory.clear)
|
71 |
+
clear.click(lambda: [], None, chatbot)
|
72 |
+
clear.click(lambda: [], None, state)
|
73 |
+
demo.launch(server_name="0.0.0.0", server_port=7861)
|
prompts.py
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
CHARTGPT_PREFIX = """ChartGPT is designed to assist with data lake visualization related tasks.
|
3 |
+
ChartGPT can extract data from text. ChartGPT can use the tool in sequence and save the visualized results to an image file, which will have a filename in the format "image/xxx.png". You will be loyal to the tool to observe the output, not fake the resulting image filename.
|
4 |
+
ChartGPT should use tools to accomplish the following tasks, not just imagine from the description. Some tools will return descriptions in English, but your chats to users should be in Chinese.
|
5 |
+
Overall, ChartGPT is a powerful data lake visualization aid that can help with a wide range of data lake visualization tasks.
|
6 |
+
TOOLS:
|
7 |
+
------
|
8 |
+
|
9 |
+
ChartGPT has access to the following tools:"""
|
10 |
+
|
11 |
+
CHARTGPT_FORMAT_INSTRUCTIONS = """To use a tool, please use the following format:
|
12 |
+
|
13 |
+
```
|
14 |
+
Thought: Do I need to use a tool? Yes
|
15 |
+
Action: the action to take, should be one of [{tool_names}]
|
16 |
+
Action Input: the input to the action
|
17 |
+
Observation: the result of the action
|
18 |
+
```
|
19 |
+
|
20 |
+
When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:
|
21 |
+
|
22 |
+
```
|
23 |
+
Thought: Do I need to use a tool? No
|
24 |
+
{ai_prefix}: [your response here]
|
25 |
+
```
|
26 |
+
"""
|
27 |
+
|
28 |
+
CHARTGPT_SUFFIX = """
|
29 |
+
Begin!
|
30 |
+
Since ChartGPT is a textual language model, tools must be used to process data rather than relying on imagination.
|
31 |
+
Reasoning ideas and observations are only visible to ChartGPT. You need to remember to repeat important information to the user in the final reply. You can only return Chinese sentences to the user. Let's think step by step. When you use the tool, the parameters of the tool can only be in English.
|
32 |
+
Previous conversation history:
|
33 |
+
{chat_history}
|
34 |
+
|
35 |
+
New input: {input}
|
36 |
+
{agent_scratchpad} Let's think step by step.
|
37 |
+
"""
|
38 |
+
|
39 |
+
CHARTGPT_PREFIX_CN = """ChartGPT 旨在能够协助完成数据可视化相关任务。
|
40 |
+
ChartGPT 能够抽取文本中的数据。 ChartGPT 能够按顺序使用工具,并且将可视化的结果保存到图片文件中,图片文件都会有一个文件名,格式为“image/xxx.png”。你将忠于工具观察输出,而不是伪造生成的图像文件名。
|
41 |
+
ChartGPT 应该使用工具来完成以下任务,而不是直接从描述中想象。有些工具将会返回英文描述,但你对用户的聊天应当采用中文。
|
42 |
+
总的来说,ChartGPT 是一个强大的数据可视化辅助工具,可以帮助处理范围广泛的数据可视化任务。
|
43 |
+
工具列表:
|
44 |
+
------
|
45 |
+
ChartGPT 可以使用这些工具:"""
|
46 |
+
|
47 |
+
CHARTGPT_FORMAT_INSTRUCTIONS_CN = """用户使用中文和你进行聊天,但是工具的参数应当使用英文。如果要调用工具,你必须遵循如下格式:
|
48 |
+
|
49 |
+
```
|
50 |
+
Thought: Do I need to use a tool? Yes
|
51 |
+
Action: the action to take, should be one of [{tool_names}]
|
52 |
+
Action Input: the input to the action
|
53 |
+
Observation: the result of the action
|
54 |
+
```
|
55 |
+
当你不再需要继续调用工具,而是对观察结果进行总结回复时,你必须使用如下格式:
|
56 |
+
```
|
57 |
+
Thought: Do I need to use a tool? No
|
58 |
+
{ai_prefix}: [your response here]
|
59 |
+
```
|
60 |
+
"""
|
61 |
+
|
62 |
+
CHARTGPT_SUFFIX_CN = """
|
63 |
+
开始!
|
64 |
+
因为ChartGPT是一个文本语言模型,必须使用工具去处理数据而不是依靠想象。
|
65 |
+
推理想法和观察结果只对ChartGPT可见,需要记得在最终回复时把重要的信息重复给用户,你只能给用户返回中文句子。我们一步一步思考。在你使用工具时,工具的参数只能是英文。
|
66 |
+
聊天历史:
|
67 |
+
{chat_history}
|
68 |
+
新输入: {input}
|
69 |
+
{agent_scratchpad}
|
70 |
+
"""
|
71 |
+
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
langchain==0.0.283
|
2 |
+
plotly==5.14.1
|
3 |
+
gradio==3.15.0
|
4 |
+
openai
|
5 |
+
kaleido
|
tools.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import uuid
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
from langchain.tools import Tool
|
5 |
+
|
6 |
+
os.makedirs('image', exist_ok=True)
|
7 |
+
|
8 |
+
|
9 |
+
def plot_bar(inputs) -> str:
|
10 |
+
inputs = eval(inputs)
|
11 |
+
image_filename = os.path.join('image', f"{str(uuid.uuid4())[:8]}.png")
|
12 |
+
fig = go.Figure(data=[go.Bar(x=list(range(len(inputs))), y=inputs)])
|
13 |
+
fig.write_image(image_filename)
|
14 |
+
print(f"\nProcessed PlotBarChart, Input arr: {inputs}, Output Text: {image_filename}")
|
15 |
+
return image_filename
|
16 |
+
|
17 |
+
|
18 |
+
def plot_line(inputs) -> str:
|
19 |
+
inputs = eval(inputs)
|
20 |
+
image_filename = os.path.join('image', f"{str(uuid.uuid4())[:8]}.png")
|
21 |
+
fig = go.Figure(data=[go.Line(x=list(range(len(inputs))), y=inputs)])
|
22 |
+
fig.write_image(image_filename)
|
23 |
+
print(f"\nProcessed PlotBarChart, Input arr: {inputs}, Output Text: {image_filename}")
|
24 |
+
return image_filename
|
25 |
+
|
26 |
+
|
27 |
+
def plot_pie(inputs: tuple) -> str:
|
28 |
+
inputs = eval(inputs)
|
29 |
+
labels = inputs[0]
|
30 |
+
values = inputs[1]
|
31 |
+
# 创建饼图对象
|
32 |
+
fig = go.Figure(data=go.Pie(labels=labels, values=values))
|
33 |
+
# 设置图表布局
|
34 |
+
fig.update_layout(title='Pie Chart')
|
35 |
+
image_filename = os.path.join('image', f"{str(uuid.uuid4())[:8]}.png")
|
36 |
+
fig.write_image(image_filename)
|
37 |
+
print(f"\nProcessed PlotPieChart, Input labels :{labels}, Input arr: {values}, Output Text: {image_filename}")
|
38 |
+
return image_filename
|
39 |
+
|
40 |
+
|
41 |
+
def plot_scatter(inputs: tuple) -> str:
|
42 |
+
inputs = eval(inputs)
|
43 |
+
# 创建散点图数据
|
44 |
+
x = inputs[0]
|
45 |
+
y = inputs[1]
|
46 |
+
# 创建散点图对象
|
47 |
+
fig = go.Figure(data=go.Scatter(
|
48 |
+
x=x, y=y, mode='markers', marker=dict(size=10, color='blue')
|
49 |
+
))
|
50 |
+
# 设置图表布局
|
51 |
+
fig.update_layout(title='Scatter Plot', xaxis_title='X-axis', yaxis_title='Y-axis')
|
52 |
+
image_filename = os.path.join('image', f"{str(uuid.uuid4())[:8]}.png")
|
53 |
+
fig.write_image(image_filename)
|
54 |
+
print(f"\nProcessed PlotScatterChart, Input x :{x}, Input y: {y}, Output Text: {image_filename}")
|
55 |
+
return image_filename
|
56 |
+
|
57 |
+
|
58 |
+
bar_tool = Tool(name="PlotBarChart", func=plot_bar,
|
59 |
+
description="useful when you want to draw bar chart. receives array as input. "
|
60 |
+
"The input to this tool should be a number list, representing the array. ",
|
61 |
+
return_direct=True)
|
62 |
+
|
63 |
+
line_tool = Tool(name="PlotLineChart", func=plot_line,
|
64 |
+
description="useful when you want to draw line chart. receives array as input. "
|
65 |
+
"The input to this tool should be a number list, representing the array. ",
|
66 |
+
return_direct=True)
|
67 |
+
|
68 |
+
pie_tool = Tool(name="PlotPieChart", func=plot_pie,
|
69 |
+
description="useful when you want to draw pie chart. the input is a tuple, which schema is such as(lables,values)."
|
70 |
+
"'labels', the first element of the input tuple, is a list of string, containing the names of each sector in the pie chart. "
|
71 |
+
"'values', the second element of the input tuple, is a list of number, containing values corresponding to each sector ",
|
72 |
+
return_direct=True)
|
73 |
+
|
74 |
+
scatter_tool = Tool(name="PlotScatterChart", func=plot_scatter,
|
75 |
+
description="useful when you want to draw scatter chart. the input is a tuple, which schema is such as(x,y)."
|
76 |
+
"'x', the first element of the input tuple, is a list containing the abscissa values of each point in the scatterplot."
|
77 |
+
"'y', the second element of the input tuple, 'is a list containing the ordinate values of each point in the scatterplot.",
|
78 |
+
return_direct=True)
|