Spaces:
Running
Running
littlebird13
commited on
Commit
•
51882e5
1
Parent(s):
fe90cb9
Update app.py
Browse files
app.py
CHANGED
@@ -1,54 +1,59 @@
|
|
1 |
# Copyright (c) Alibaba, Inc. and its affiliates.
|
2 |
import os
|
|
|
|
|
|
|
|
|
3 |
|
4 |
import gradio as gr
|
5 |
import modelscope_studio.components.antd as antd
|
6 |
import modelscope_studio.components.base as ms
|
7 |
from PIL import Image
|
8 |
-
import secrets
|
9 |
-
import tempfile
|
10 |
-
from http import HTTPStatus
|
11 |
from urllib3.exceptions import HTTPError
|
12 |
|
13 |
-
|
14 |
-
|
15 |
|
16 |
import dashscope
|
17 |
from dashscope import MultiModalConversation
|
18 |
-
|
19 |
-
|
20 |
dashscope.api_key = API_KEY
|
21 |
-
dashscope.base_http_api_url = BASE_URL
|
22 |
|
23 |
is_modelscope_studio = os.getenv('MODELSCOPE_ENVIRONMENT') == 'studio'
|
24 |
|
|
|
25 |
def get_text(text: str, cn_text: str):
|
26 |
if is_modelscope_studio:
|
27 |
return cn_text
|
28 |
return text
|
29 |
|
|
|
30 |
def resolve_image(filename):
|
31 |
return os.path.join(os.path.dirname(__file__), filename)
|
32 |
|
|
|
33 |
DEMO_LIST = [
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
50 |
]
|
51 |
|
|
|
52 |
def process_image(image, shouldConvert=False):
|
53 |
# 获取上传文件的目录
|
54 |
uploaded_file_dir = os.environ.get("GRADIO_TEMP_DIR") or str(
|
@@ -69,114 +74,131 @@ def process_image(image, shouldConvert=False):
|
|
69 |
|
70 |
return filename
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
with antd.Space(direction="vertical",
|
109 |
-
elem_style=dict(width="100%")
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
output = gr.Markdown(
|
179 |
show_copy_button=True,
|
|
|
180 |
latex_delimiters=[{
|
181 |
"left": '$$',
|
182 |
"right": '$$',
|
@@ -194,66 +216,83 @@ if __name__ == "__main__":
|
|
194 |
"right": '\\]',
|
195 |
"display": True
|
196 |
}])
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
imageFile = process_image(image)
|
223 |
-
content
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
}
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# Copyright (c) Alibaba, Inc. and its affiliates.
|
2 |
import os
|
3 |
+
import secrets
|
4 |
+
import tempfile
|
5 |
+
from http import HTTPStatus
|
6 |
+
from pathlib import Path
|
7 |
|
8 |
import gradio as gr
|
9 |
import modelscope_studio.components.antd as antd
|
10 |
import modelscope_studio.components.base as ms
|
11 |
from PIL import Image
|
|
|
|
|
|
|
12 |
from urllib3.exceptions import HTTPError
|
13 |
|
14 |
+
os.environ['DASHSCOPE_HTTP_BASE_URL'] = 'https://dashscope.aliyuncs.com/api/v1'
|
15 |
+
# os.environ['DASHSCOPE_WEBSOCKET_BASE_URL'] = 'https://poc-dashscope.aliyuncs.com/api-ws/v1/inference'
|
16 |
|
17 |
import dashscope
|
18 |
from dashscope import MultiModalConversation
|
19 |
+
|
20 |
+
API_KEY = os.environ.get('API_KEY')
|
21 |
dashscope.api_key = API_KEY
|
|
|
22 |
|
23 |
is_modelscope_studio = os.getenv('MODELSCOPE_ENVIRONMENT') == 'studio'
|
24 |
|
25 |
+
|
26 |
def get_text(text: str, cn_text: str):
|
27 |
if is_modelscope_studio:
|
28 |
return cn_text
|
29 |
return text
|
30 |
|
31 |
+
|
32 |
def resolve_image(filename):
|
33 |
return os.path.join(os.path.dirname(__file__), filename)
|
34 |
|
35 |
+
|
36 |
DEMO_LIST = [
|
37 |
+
{
|
38 |
+
"description":
|
39 |
+
"Evaluate the integral of the functions graphed using the formula for circles: ",
|
40 |
+
"image": resolve_image("./examples/1.webp")
|
41 |
+
},
|
42 |
+
{
|
43 |
+
"description": "请解答这道题",
|
44 |
+
"image": resolve_image("./examples/5.png")
|
45 |
+
},
|
46 |
+
{
|
47 |
+
"description": "图片中的滤液E是什么化学物质?",
|
48 |
+
"image": resolve_image("./examples/3.png")
|
49 |
+
},
|
50 |
+
{
|
51 |
+
"description": "How many pelicans are there in the picture",
|
52 |
+
"image": resolve_image("./examples/6.png")
|
53 |
+
},
|
54 |
]
|
55 |
|
56 |
+
|
57 |
def process_image(image, shouldConvert=False):
|
58 |
# 获取上传文件的目录
|
59 |
uploaded_file_dir = os.environ.get("GRADIO_TEMP_DIR") or str(
|
|
|
74 |
|
75 |
return filename
|
76 |
|
77 |
+
|
78 |
+
def on_clear():
|
79 |
+
return {
|
80 |
+
input: gr.update(value=None),
|
81 |
+
**{
|
82 |
+
item: gr.update(value=None)
|
83 |
+
for item in input_image
|
84 |
+
},
|
85 |
+
}
|
86 |
+
|
87 |
+
|
88 |
+
css = """
|
89 |
+
.output-markdown {
|
90 |
+
overflow: unset !important;
|
91 |
+
}
|
92 |
+
"""
|
93 |
+
|
94 |
+
with gr.Blocks(css=css) as demo:
|
95 |
+
with ms.Application() as app:
|
96 |
+
with antd.ConfigProvider(
|
97 |
+
locale="zh_CN" if is_modelscope_studio else None,
|
98 |
+
theme=dict(token=dict(colorPrimary="#a855f7"))):
|
99 |
+
with antd.Card(elem_style=dict(marginBottom=12),
|
100 |
+
styles=dict(body=dict(padding=4))):
|
101 |
+
with antd.Flex(elem_style=dict(width="100%"),
|
102 |
+
justify="center",
|
103 |
+
align="center",
|
104 |
+
gap=14):
|
105 |
+
with ms.Div(elem_style=dict(flexShrink=0)):
|
106 |
+
antd.Image(resolve_image("./cutelogo.jpg"),
|
107 |
+
preview=False,
|
108 |
+
height=60,
|
109 |
+
width=60)
|
110 |
+
with ms.Div():
|
111 |
+
antd.Typography.Title("QVQ-72B-Preview",
|
112 |
+
elem_style=dict(margin=0,
|
113 |
+
fontSize=24),
|
114 |
+
level=1)
|
115 |
+
with ms.AutoLoading():
|
116 |
+
with antd.Row(gutter=[8, 8], align="stretch"):
|
117 |
+
with antd.Col(xs=24, md=8):
|
118 |
+
with antd.Space(direction="vertical",
|
119 |
+
elem_style=dict(width="100%")):
|
120 |
with antd.Space(direction="vertical",
|
121 |
+
elem_style=dict(width="100%"),
|
122 |
+
elem_id="input-container"):
|
123 |
+
with ms.Fragment():
|
124 |
+
input_image = gr.Image(type="pil",
|
125 |
+
label="Upload",
|
126 |
+
sources=["upload"]),
|
127 |
+
input = antd.Input.Textarea(
|
128 |
+
placeholder=get_text(
|
129 |
+
"Ask a question", "输入一个问题"),
|
130 |
+
auto_size=dict(maxRows=6, minRows=2),
|
131 |
+
allow_clear=True)
|
132 |
+
|
133 |
+
with antd.Flex(align="center",
|
134 |
+
justify="space-between"):
|
135 |
+
antd.Typography.Text(get_text(
|
136 |
+
"Warning: This model only supports single-turn dialogue.",
|
137 |
+
"注:当前模型只支持单轮对话,如需中文回答,提示词加“用中文回答”"),
|
138 |
+
type="warning")
|
139 |
+
tour_btn = antd.Button(get_text(
|
140 |
+
"Tour", "使用指引"),
|
141 |
+
variant="filled",
|
142 |
+
color="default")
|
143 |
+
|
144 |
+
with antd.Row(gutter=8):
|
145 |
+
with antd.Col(span=12):
|
146 |
+
clear_btn = antd.Button(get_text(
|
147 |
+
"Clear", "清除"),
|
148 |
+
block=True)
|
149 |
+
with antd.Col(span=12):
|
150 |
+
submit_btn = antd.Button(
|
151 |
+
get_text("Submit", "提交"),
|
152 |
+
type="primary",
|
153 |
+
block=True,
|
154 |
+
elem_id="submit-btn")
|
155 |
+
|
156 |
+
antd.Divider(get_text("Examples", "示例"))
|
157 |
+
|
158 |
+
with antd.Flex(gap="small", wrap=True):
|
159 |
+
for item in DEMO_LIST:
|
160 |
+
|
161 |
+
def bind_on_example(_item):
|
162 |
+
|
163 |
+
def on_example():
|
164 |
+
return gr.update(
|
165 |
+
value=_item['description']
|
166 |
+
), gr.update(value=_item['image'])
|
167 |
+
|
168 |
+
return on_example
|
169 |
+
|
170 |
+
with antd.Card(
|
171 |
+
hoverable=True,
|
172 |
+
elem_style=dict(
|
173 |
+
width="100%")) as example:
|
174 |
+
if "description" in item:
|
175 |
+
antd.Typography.Text(
|
176 |
+
item["description"])
|
177 |
+
if "image" in item:
|
178 |
+
antd.Image(item["image"],
|
179 |
+
preview=False)
|
180 |
+
example.click(
|
181 |
+
fn=bind_on_example(item),
|
182 |
+
outputs=[input, input_image[0]])
|
183 |
+
|
184 |
+
with antd.Col(xs=24, md=16):
|
185 |
+
with antd.Card(title=get_text("Answer", "答案"),
|
186 |
+
elem_style=dict(height="100%"),
|
187 |
+
elem_id="output-container"):
|
188 |
+
with ms.Slot("extra"):
|
189 |
+
cancel_btn = antd.Button(get_text(
|
190 |
+
"Stop", "停止"),
|
191 |
+
elem_id="cancel-btn",
|
192 |
+
block=True,
|
193 |
+
disabled=True)
|
194 |
+
with ms.Div(elem_style=dict(
|
195 |
+
maxHeight=1600,
|
196 |
+
display="flex",
|
197 |
+
flexDirection="column-reverse",
|
198 |
+
overflow="auto")):
|
199 |
output = gr.Markdown(
|
200 |
show_copy_button=True,
|
201 |
+
elem_classes="output-markdown",
|
202 |
latex_delimiters=[{
|
203 |
"left": '$$',
|
204 |
"right": '$$',
|
|
|
216 |
"right": '\\]',
|
217 |
"display": True
|
218 |
}])
|
219 |
+
with antd.Tour(open=False) as tour:
|
220 |
+
antd.Tour.Step(
|
221 |
+
title=get_text("Step 1", "步骤 1"),
|
222 |
+
description=get_text("Upload image and enter text",
|
223 |
+
"传入图片和文本"),
|
224 |
+
get_target=
|
225 |
+
"() => document.querySelector('#input-container')")
|
226 |
+
antd.Tour.Step(
|
227 |
+
title=get_text("Step 2", "步骤 2"),
|
228 |
+
description=get_text("Click the submit button",
|
229 |
+
"点击提交按钮"),
|
230 |
+
get_target="() => document.querySelector('#submit-btn')"
|
231 |
+
)
|
232 |
+
antd.Tour.Step(
|
233 |
+
title=get_text("Step 3", "步骤 3"),
|
234 |
+
description=get_text("Wait for the result", "等待结果返回"),
|
235 |
+
get_target=
|
236 |
+
"() => document.querySelector('#output-container')")
|
237 |
+
antd.Tour.Step(
|
238 |
+
title=get_text("Tips", "提示"),
|
239 |
+
description=get_text("Click here to end output early",
|
240 |
+
"点击这里提前结束输出"),
|
241 |
+
get_target="() => document.querySelector('#cancel-btn')"
|
242 |
+
)
|
243 |
+
|
244 |
+
tour_btn.click(fn=lambda: gr.update(open=True), outputs=[tour])
|
245 |
+
gr.on([tour.finish, tour.close],
|
246 |
+
fn=lambda: gr.update(open=False),
|
247 |
+
outputs=[tour])
|
248 |
+
|
249 |
+
def generate(image, query):
|
250 |
+
content = []
|
251 |
+
if not image and not query:
|
252 |
+
raise gr.Error(
|
253 |
+
get_text("Error: Input is empty", "错误:输入内容为空"))
|
254 |
+
if image:
|
255 |
imageFile = process_image(image)
|
256 |
+
content.append({'image': f'file://{imageFile}'})
|
257 |
+
if query:
|
258 |
+
content.append({'text': query})
|
259 |
+
|
260 |
+
print("image", image)
|
261 |
+
print("query", query)
|
262 |
+
messages = [
|
263 |
+
{
|
264 |
+
'role': 'user',
|
265 |
+
'content': content
|
266 |
+
},
|
267 |
+
]
|
268 |
+
|
269 |
+
responses = MultiModalConversation.call(
|
270 |
+
model='qvq-72b-preview',
|
271 |
+
messages=messages,
|
272 |
+
stream=True,
|
273 |
+
)
|
274 |
+
yield {cancel_btn: gr.update(disabled=False)}
|
275 |
+
for response in responses:
|
276 |
+
if not response.status_code == HTTPStatus.OK:
|
277 |
+
raise HTTPError(
|
278 |
+
f'response.code: {response.code}\nresponse.message: {response.message}'
|
279 |
+
)
|
280 |
+
response = response.output.choices[0].message.content
|
281 |
+
if len(response) > 0 and response[0]['text']:
|
282 |
+
print(response[0]['text'])
|
283 |
+
yield {output: response[0]['text']}
|
284 |
+
yield {cancel_btn: gr.update(disabled=True)}
|
285 |
+
|
286 |
+
output_process = submit_btn.click(fn=generate,
|
287 |
+
inputs=[*input_image, input],
|
288 |
+
outputs=[output, cancel_btn])
|
289 |
+
clear_btn.click(fn=on_clear, outputs=[*input_image, input])
|
290 |
+
cancel_btn.click(fn=None,
|
291 |
+
inputs=None,
|
292 |
+
outputs=None,
|
293 |
+
cancels=[output_process])
|
294 |
+
cancel_btn.click(fn=lambda: gr.update(disabled=True),
|
295 |
+
inputs=None,
|
296 |
+
outputs=[cancel_btn])
|
297 |
+
|
298 |
+
demo.queue(default_concurrency_limit=50).launch(ssr_mode=False)
|