remiserra commited on
Commit
37c29c8
·
1 Parent(s): 8afb9aa
Files changed (6) hide show
  1. app.py +366 -0
  2. data_images.py +2 -0
  3. prompts.py +114 -0
  4. requirements.txt +2 -0
  5. svg_utils.py +26 -0
  6. watsonx_utils.py +92 -0
app.py ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Remi Serra 202407
2
+
3
+ import gradio as gr
4
+ from random import randrange
5
+ from svg_utils import decode_b64_string_to_pretty_xml, encode_svg_xml_to_b64_string
6
+ from watsonx_utils import wxEngine
7
+ from prompts import (
8
+ list_prompts,
9
+ get_prompt_template,
10
+ get_prompt_example,
11
+ get_prompt_primer,
12
+ )
13
+ from data_images import svg_three_dots
14
+
15
+
16
+ # Functions
17
+ def read_file(uploaded_file):
18
+ if uploaded_file:
19
+ svg_xml = open(uploaded_file, "r").read()
20
+ data_string = xml_string_to_data_string(svg_xml)
21
+ return (
22
+ data_string,
23
+ svg_xml,
24
+ html_img_preview(data_string),
25
+ xml_string_to_html_img(svg_xml),
26
+ )
27
+
28
+
29
+ def encoded_string_box_change(data_string: str):
30
+ # print(f"encoded_string_box_change:image_data:{data_string}")
31
+ svg_xml = decode_b64_string_to_pretty_xml(data_string)
32
+ return svg_xml, html_img_preview(data_string), xml_string_to_html_img(svg_xml)
33
+
34
+
35
+ def xml_string_box_change(svg_xml: str):
36
+ data_string = xml_string_to_data_string(svg_xml)
37
+ return data_string, html_img_preview(data_string), xml_string_to_html_img(svg_xml)
38
+
39
+
40
+ def xml_string_to_data_string(svg_xml: str):
41
+ b64 = encode_svg_xml_to_b64_string(svg_xml)
42
+ data_string = "data:image/svg+xml;base64," + b64
43
+ return data_string
44
+
45
+
46
+ def html_img_preview(data_string):
47
+ return r'<center><img width=100 src="%s"/><center>' % data_string
48
+
49
+
50
+ def xml_string_to_html_img(svg_xml: str):
51
+ data_string = xml_string_to_data_string(svg_xml)
52
+ return html_img_preview(data_string)
53
+
54
+
55
+ # def replace_color(svg_xml: str, color_from, color_to):
56
+ # print(
57
+ # f"replace_color:svg_xml:{svg_xml}, color_from:{color_from}, color_to:{color_to} "
58
+ # )
59
+ # if svg_xml and color_from and color_to:
60
+ # new_svg_xml = svg_xml.replace(color_from, color_to)
61
+ # data_string = xml_string_to_data_string(new_svg_xml)
62
+ # return data_string, new_svg_xml, html_img_preview(data_string)
63
+
64
+
65
+ # def switch_colors(color_from, color_to):
66
+ # print(f"switch_colors:color_from:{color_from}, color_to:{color_to} ")
67
+ # return color_to, color_from
68
+
69
+
70
+ # Functions - watsonx
71
+
72
+
73
+ def wx_prompt_change(prompt_template_name):
74
+ return (
75
+ get_prompt_template(prompt_template_name),
76
+ get_prompt_example(prompt_template_name),
77
+ get_prompt_primer(prompt_template_name),
78
+ )
79
+
80
+
81
+ def wx_models_dropdown(wx_engine_state):
82
+ wx_engine = wx_engine_state
83
+ model_list = []
84
+ default_value = None
85
+ recommended_model = "ibm/granite-20b-code-instruct"
86
+ if wx_engine is not None:
87
+ model_list = wx_engine.list_models()
88
+ default_value = (
89
+ (recommended_model if recommended_model in model_list else model_list[0]),
90
+ )
91
+ return gr.Dropdown(
92
+ label="Model",
93
+ info=recommended_model + " recommended",
94
+ choices=model_list,
95
+ value=default_value,
96
+ )
97
+
98
+
99
+ def wx_connect(wx_engine_state, apiendpoint, apikey, projectid):
100
+ wx_engine_state = wxEngine(apiendpoint, apikey, projectid)
101
+ print("watsonx.ai activated")
102
+ return wx_engine_state, wx_models_dropdown(wx_engine_state)
103
+
104
+
105
+ def prepare_prompt(
106
+ wx_engine_state, wx_model, wx_prompt, wx_instructions, wx_primer="", xml_string=""
107
+ ):
108
+ wx_status = "Done."
109
+ wx_engine = wx_engine_state
110
+ # get model specs
111
+ model_max_tokens = wx_engine.get_model_max_tokens(wx_model)
112
+ # Add "primer" at the end of the prompt
113
+ prompt = wx_prompt.format(svg=xml_string, instructions=wx_instructions) + wx_primer
114
+ # Test and alert if prompt is too long
115
+ prompt_nb_tokens = wx_engine.get_prompt_nb_tokens(prompt, wx_model)
116
+ if prompt_nb_tokens > model_max_tokens:
117
+ wx_status = f"Warning: prompt length ({prompt_nb_tokens}) is more than the model max tokens ({model_max_tokens}), and will be truncated. Please review your instructions."
118
+ print(wx_status)
119
+ # calculate max new token based on xml_string - or 500 when original string is too small
120
+ # note: prompt will be truncated if too long with GenTextParamsMetaNames.TRUNCATE_INPUT_TOKENS in generate()
121
+ max_new_tokens = max(500, len(xml_string))
122
+ return wx_status, max_new_tokens, prompt
123
+
124
+
125
+ def wx_generate(
126
+ wx_engine_state, wx_model, wx_prompt, wx_instructions, wx_primer="", xml_string=""
127
+ ):
128
+ wx_engine = wx_engine_state
129
+ wx_status, max_new_tokens, prompt = prepare_prompt(
130
+ wx_engine, wx_model, wx_prompt, wx_instructions, wx_primer, xml_string
131
+ )
132
+ wx_result = wx_primer + wx_engine.generate_text(
133
+ modelid=wx_model,
134
+ prompt=prompt,
135
+ max_new_tokens=max_new_tokens,
136
+ stop_sequences=["</svg>"],
137
+ )
138
+ print(f"wx_generate:wx_result:{wx_result}")
139
+ return wx_status, wx_result, xml_string_to_html_img(wx_result)
140
+
141
+
142
+ def wx_stream(
143
+ wx_engine_state, wx_model, wx_prompt, wx_instructions, wx_primer="", xml_string=""
144
+ ):
145
+ wx_engine = wx_engine_state
146
+ wx_status, max_new_tokens, prompt = prepare_prompt(
147
+ wx_engine, wx_model, wx_prompt, wx_instructions, wx_primer, xml_string
148
+ )
149
+ wx_result = wx_primer
150
+ # https://www.gradio.app/guides/streaming-outputs
151
+ wx_result_generator = wx_engine.generate_text(
152
+ modelid=wx_model,
153
+ prompt=prompt,
154
+ max_new_tokens=max_new_tokens,
155
+ stop_sequences=["</svg>"],
156
+ stream=True,
157
+ )
158
+ for chunk in wx_result_generator:
159
+ wx_result += chunk
160
+ yield f"Processing.{"."*int(randrange(3))}", wx_result, None
161
+ print(f"wx_stream:wx_result:{wx_result}")
162
+ yield wx_status, wx_result, xml_string_to_html_img(wx_result)
163
+
164
+
165
+ def wx_result_box_change(wx_result):
166
+ return xml_string_to_html_img(wx_result)
167
+
168
+
169
+ def wx_accept(svg_xml):
170
+ data_string = xml_string_to_data_string(svg_xml)
171
+ return (
172
+ data_string,
173
+ svg_xml,
174
+ html_img_preview(data_string),
175
+ xml_string_to_html_img(svg_xml),
176
+ )
177
+
178
+
179
+ # APP
180
+ with gr.Blocks() as demo:
181
+ gr.Markdown("# SVG editor")
182
+ with gr.Accordion("Get started:", open=True):
183
+ gr.Markdown(
184
+ """
185
+ - Create a new SVG: Select the prompt template 'Create SVG', enter a description in the 'Instructions' box and click 'Submit'
186
+ - Modify an existing SVG: Upload an SVG file, or paste an image string or SVG XML, then Select the prompt template 'Modify SVG', enter a change instruction in the 'Instructions' box and click 'Submit'
187
+ - Describe an SVG: Upload, paste or generate an SVG file, Select the prompt template 'Describe SVG' and click 'Submit' """
188
+ )
189
+
190
+ # init state - note gr.State() initial value must be deep-copyable - my wx_engine class is not
191
+ wx_engine_state = gr.State(None)
192
+ with gr.Column():
193
+ # Encoded string and preview
194
+ with gr.Accordion("Load SVG:", open=True):
195
+ with gr.Row():
196
+ # Upload an .svg file
197
+ uploaded_file = gr.File(scale=0, label="Upload an SVG file")
198
+ # Paste an image string
199
+ encoded_string_box = gr.Textbox(
200
+ label="Image string",
201
+ info="data:image/svg+xml;base64,...",
202
+ lines=7,
203
+ max_lines=7,
204
+ show_copy_button=True,
205
+ scale=3,
206
+ )
207
+ # original preview
208
+ encoded_svg_preview = gr.HTML(f"<img src='{svg_three_dots}'/>")
209
+ # Decoded string and preview
210
+ with gr.Row():
211
+ xml_string_box = gr.Textbox(
212
+ label="SVG XML",
213
+ lines=7,
214
+ max_lines=7,
215
+ show_copy_button=True,
216
+ scale=3,
217
+ )
218
+ # decoded preview
219
+ decoded_svg_preview = gr.HTML(f"<img src='{svg_three_dots}'/>")
220
+ # with gr.Row(): # Color changer
221
+ # color_from_area = gr.ColorPicker(label="Search color:", value="#000000", scale=0)
222
+ # color_switch_btn = gr.Button("<->", scale=0)
223
+ # color_to_area = gr.ColorPicker(label="Replace color:", value="#FFFFFF", scale=0)
224
+ # color_replace_btn = gr.Button("Replace", scale=0)
225
+
226
+ with gr.Accordion("watsonx.ai:", open=True):
227
+ with gr.Row(): # watsonx
228
+ with gr.Column(scale=0):
229
+ with gr.Group():
230
+ # credentials
231
+ with gr.Accordion("Credentials:", open=True):
232
+ wx_creds_endpoint = gr.Textbox(
233
+ label="Endpoint", value="https://us-south.ml.cloud.ibm.com", max_lines=1
234
+ )
235
+ wx_creds_apikey = gr.Textbox(
236
+ label="API key", max_lines=1
237
+ )
238
+ wx_creds_projectid = gr.Textbox(
239
+ label="Project id", max_lines=1
240
+ )
241
+ wx_connect_btn = gr.Button("Connect")
242
+ # model
243
+ wx_models_drop = wx_models_dropdown(None)
244
+ wx_connect_btn.click(
245
+ fn=wx_connect,
246
+ inputs=[
247
+ wx_engine_state,
248
+ wx_creds_endpoint,
249
+ wx_creds_apikey,
250
+ wx_creds_projectid,
251
+ ],
252
+ outputs=[wx_engine_state, wx_models_drop],
253
+ )
254
+ # prompt template
255
+ prompt_template_names = list_prompts()
256
+ wx_prompt_drop = gr.Dropdown(
257
+ label="Prompt template",
258
+ choices=prompt_template_names,
259
+ value=prompt_template_names[0],
260
+ )
261
+ wx_prompt_box = gr.Textbox(
262
+ info="Text",
263
+ show_label=False,
264
+ max_lines=5,
265
+ value=get_prompt_template(prompt_template_names[0]),
266
+ )
267
+ wx_primer_box = gr.Textbox(
268
+ info="Primer",
269
+ show_label=False,
270
+ max_lines=2,
271
+ value=get_prompt_primer(prompt_template_names[0]),
272
+ )
273
+ with gr.Column():
274
+ with gr.Row():
275
+ wx_instructions_box = gr.Textbox(
276
+ label="Instructions",
277
+ scale=3,
278
+ value=get_prompt_example(prompt_template_names[0]),
279
+ show_copy_button=True,
280
+ )
281
+ wx_submit_btn = gr.Button("↓Submit↓", scale=0)
282
+ wx_accept_btn = gr.Button("↑Accept↑", scale=0)
283
+ with gr.Row():
284
+ wx_result_box = gr.Textbox(
285
+ label="Result",
286
+ lines=7,
287
+ max_lines=7,
288
+ scale=3,
289
+ show_copy_button=True,
290
+ )
291
+ wx_svg_preview = gr.HTML(f"<img src='{svg_three_dots}'/>")
292
+ wx_status_box = gr.Markdown("Status")
293
+
294
+ wx_prompt_drop.input(
295
+ fn=wx_prompt_change,
296
+ inputs=wx_prompt_drop,
297
+ outputs=[wx_prompt_box, wx_instructions_box, wx_primer_box],
298
+ )
299
+ wx_submit_btn.click(
300
+ # fn=wx_generate,
301
+ fn=wx_stream,
302
+ inputs=[
303
+ wx_engine_state,
304
+ wx_models_drop,
305
+ wx_prompt_box,
306
+ wx_instructions_box,
307
+ wx_primer_box,
308
+ xml_string_box,
309
+ ],
310
+ outputs=[wx_status_box, wx_result_box, wx_svg_preview],
311
+ api_name="wx_generate",
312
+ )
313
+ wx_result_box.input(
314
+ fn=wx_result_box_change,
315
+ inputs=[wx_result_box],
316
+ outputs=[wx_svg_preview],
317
+ )
318
+ wx_accept_btn.click(
319
+ fn=wx_accept,
320
+ inputs=[wx_result_box],
321
+ outputs=[
322
+ encoded_string_box,
323
+ xml_string_box,
324
+ encoded_svg_preview,
325
+ decoded_svg_preview,
326
+ ],
327
+ )
328
+
329
+ # Actions
330
+ encoded_string_box.input(
331
+ fn=encoded_string_box_change,
332
+ inputs=[encoded_string_box],
333
+ outputs=[xml_string_box, encoded_svg_preview, decoded_svg_preview],
334
+ )
335
+ uploaded_file.upload(
336
+ fn=read_file,
337
+ inputs=uploaded_file,
338
+ outputs=[
339
+ encoded_string_box,
340
+ xml_string_box,
341
+ encoded_svg_preview,
342
+ decoded_svg_preview,
343
+ ],
344
+ )
345
+ xml_string_box.input(
346
+ fn=xml_string_box_change,
347
+ inputs=[xml_string_box],
348
+ outputs=[encoded_string_box, encoded_svg_preview, decoded_svg_preview],
349
+ )
350
+ # color_switch_btn.click(
351
+ # fn=switch_colors,
352
+ # inputs=[color_from_area, color_to_area],
353
+ # outputs=[color_from_area, color_to_area],
354
+ # api_name="color_switch",
355
+ # )
356
+ # color_replace_btn.click(
357
+ # fn=replace_color,
358
+ # inputs=[xml_string_box, color_from_area, color_to_area],
359
+ # outputs=[encoded_string_box, xml_string_box, svg_preview],
360
+ # api_name="color_replace",
361
+ # )
362
+
363
+
364
+ # Main
365
+ if __name__ == "__main__":
366
+ demo.launch()
data_images.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Remi Serra 202407
2
+ svg_three_dots = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiPgogIDxjaXJjbGUgY3g9IjEwIiBjeT0iMTAiIHI9IjUiIGZpbGw9InJlZCIgLz4KICA8Y2lyY2xlIGN4PSIzMCIgY3k9IjEwIiByPSI1IiBmaWxsPSJncmVlbiIgLz4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjEwIiByPSI1IiBmaWxsPSJibHVlIiAvPgo8L3N2Zz4="
prompts.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Remi Serra 202407
2
+ svg_prompts = {
3
+ "Create SVG": {
4
+ "template": """You are an expert of the SVG image format. You will be provided with the description of an image.
5
+ Design the SVG to create the image and return the new SVG image XML. Do not provide comments, only the resulting SVG XML.
6
+
7
+ Instructions:
8
+ {instructions}
9
+
10
+ Result SVG XML:
11
+ """,
12
+ "display": True,
13
+ "example": "Tree dots",
14
+ "primer": '<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg"',
15
+ },
16
+ "Modify SVG": {
17
+ "template": """You are an expert of the SVG image format.
18
+ You will be provided with an SVG image XML representation and modification instructions.
19
+ Apply the instructions to the SVG XML and return the new SVG image XML. Do not provide comments, only the resulting SVG XML.
20
+
21
+ SVG XML:
22
+ {svg}
23
+
24
+ Instructions:
25
+ {instructions}
26
+
27
+ Result SVG XML:
28
+ """,
29
+ "display": True,
30
+ "example": "Change all colors to red",
31
+ "primer": "",
32
+ },
33
+ "Describe SVG": {
34
+ "template": """You are an expert of the SVG image format.
35
+ You will be provided with an SVG image XML representation, please describe the image provided.
36
+ Try to describe the overall image, not only the details.
37
+
38
+ SVG XML:
39
+ {svg}
40
+
41
+ Description of the image:
42
+ """,
43
+ "display": True,
44
+ "example": "N/A",
45
+ "primer": "",
46
+ },
47
+ "Create IBM style SVG": {
48
+ "template": """You are an expert of the SVG image format and of IBM design style.
49
+ You will be provided with a few samples of IBM style SVG image,
50
+ Then you will be provided with the description of an image.
51
+ Design a new SVG to create the image and return the new SVG image XML.
52
+ Do not provide comments, only the resulting SVG XML.
53
+
54
+
55
+ SVG XML Sample in IBM design style:
56
+
57
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
58
+ <rect width="16" height="16" fill="white" fill-opacity="0.01" style="mix-blend-mode:multiply"/>
59
+ <path d="M8 14C6.9122 14 5.84883 13.6774 4.94436 13.0731C4.03989 12.4687 3.33494 11.6098 2.91866 10.6048C2.50238 9.59977 2.39346 8.4939 2.60568 7.42701C2.8179 6.36011 3.34172 5.38011 4.11091 4.61092C4.8801 3.84173 5.86011 3.3179 6.927 3.10568C7.9939 2.89347 9.09977 3.00238 10.1048 3.41867C11.1098 3.83495 11.9687 4.5399 12.5731 5.44437C13.1774 6.34884 13.5 7.41221 13.5 8.5C13.5 9.95869 12.9205 11.3576 11.8891 12.3891C10.8576 13.4205 9.45869 14 8 14ZM8 4C7.10998 4 6.23995 4.26392 5.49993 4.75839C4.75991 5.25286 4.18314 5.95566 3.84254 6.77793C3.50195 7.6002 3.41283 8.505 3.58647 9.37791C3.7601 10.2508 4.18868 11.0526 4.81802 11.682C5.44736 12.3113 6.24918 12.7399 7.12209 12.9135C7.99501 13.0872 8.89981 12.9981 9.72208 12.6575C10.5443 12.3169 11.2471 11.7401 11.7416 11.0001C12.2361 10.26 12.5 9.39002 12.5 8.5C12.5 7.30653 12.0259 6.16194 11.182 5.31802C10.3381 4.47411 9.19347 4 8 4Z" fill="#161616"/>
60
+ <path d="M3.79082 2.00158L2.00018 3.79597L2.70803 4.50234L4.49867 2.70795L3.79082 2.00158Z" fill="#161616"/>
61
+ <path d="M12.2076 1.99719L11.4997 2.70356L13.2904 4.49795L13.9982 3.79158L12.2076 1.99719Z" fill="#161616"/>
62
+ <path d="M10.5 8H5.5V9H10.5V8Z" fill="#161616"/>
63
+ </svg>
64
+
65
+
66
+ SVG XML Sample in IBM design style:
67
+
68
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
69
+ <rect width="16" height="16" fill="white" fill-opacity="0.01" style="mix-blend-mode:multiply"/>
70
+ <path d="M15 7.5H13V6C12.9997 5.73488 12.8942 5.48072 12.7067 5.29326C12.5193 5.10579 12.2651 5.00033 12 5H10C9.73489 5.00033 9.48072 5.10579 9.29326 5.29326C9.10579 5.48072 9.00033 5.73488 9 6V7.5H7V4C6.99967 3.73489 6.89421 3.48072 6.70674 3.29326C6.51928 3.10579 6.26511 3.00033 6 3H4C3.73488 3.00033 3.48072 3.10579 3.29326 3.29326C3.10579 3.48072 3.00033 3.73489 3 4V7.5H1V8.5H3V12C3.00033 12.2651 3.10579 12.5193 3.29326 12.7067C3.48072 12.8942 3.73488 12.9997 4 13H6C6.26511 12.9997 6.51928 12.8942 6.70674 12.7067C6.89421 12.5193 6.99967 12.2651 7 12V8.5H9V10C9.00033 10.2651 9.10579 10.5193 9.29326 10.7067C9.48072 10.8942 9.73489 10.9997 10 11H12C12.2651 10.9997 12.5193 10.8942 12.7067 10.7067C12.8942 10.5193 12.9997 10.2651 13 10V8.5H15V7.5ZM4 12V4H6L6.0006 12H4ZM10 10V6H12L12.0006 10H10Z" fill="#161616"/>
71
+ </svg>
72
+
73
+
74
+ SVG XML Sample in IBM design style:
75
+
76
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
77
+ <rect width="16" height="16" fill="white" fill-opacity="0.01" style="mix-blend-mode:multiply"/>
78
+ <path d="M13.5 11.071V4.92905C13.8411 4.84157 14.153 4.66539 14.404 4.4184C14.655 4.17141 14.8362 3.86239 14.9292 3.52273C15.0222 3.18306 15.0236 2.82485 14.9334 2.48444C14.8432 2.14404 14.6645 1.83357 14.4155 1.58456C14.1665 1.33554 13.856 1.15685 13.5156 1.06662C13.1752 0.976392 12.817 0.977839 12.4773 1.07082C12.1376 1.16379 11.8286 1.34499 11.5816 1.59601C11.3346 1.84702 11.1585 2.15893 11.071 2.50005H4.92899C4.84151 2.15893 4.66533 1.84702 4.41834 1.59601C4.17135 1.34499 3.86233 1.16379 3.52267 1.07082C3.183 0.977839 2.82479 0.976392 2.48438 1.06662C2.14398 1.15685 1.83351 1.33554 1.5845 1.58456C1.33548 1.83357 1.15679 2.14404 1.06656 2.48444C0.976331 2.82485 0.977778 3.18306 1.07075 3.52273C1.16373 3.86239 1.34493 4.17141 1.59594 4.4184C1.84696 4.66539 2.15887 4.84157 2.49999 4.92905V11.071C2.15887 11.1585 1.84696 11.3347 1.59594 11.5817C1.34493 11.8287 1.16373 12.1377 1.07075 12.4774C0.977778 12.817 0.976331 13.1752 1.06656 13.5157C1.15679 13.8561 1.33548 14.1665 1.5845 14.4155C1.83351 14.6646 2.14398 14.8432 2.48438 14.9335C2.82479 15.0237 3.183 15.0223 3.52267 14.9293C3.86233 14.8363 4.17135 14.6551 4.41834 14.4041C4.66533 14.1531 4.84151 13.8412 4.92899 13.5H11.071C11.1585 13.8412 11.3346 14.1531 11.5816 14.4041C11.8286 14.6551 12.1376 14.8363 12.4773 14.9293C12.817 15.0223 13.1752 15.0237 13.5156 14.9335C13.856 14.8432 14.1665 14.6646 14.4155 14.4155C14.6645 14.1665 14.8432 13.8561 14.9334 13.5157C15.0236 13.1752 15.0222 12.817 14.9292 12.4774C14.8362 12.1377 14.655 11.8287 14.404 11.5817C14.153 11.3347 13.8411 11.1585 13.5 11.071ZM13 2.00005C13.1978 2.00005 13.3911 2.0587 13.5556 2.16858C13.72 2.27846 13.8482 2.43464 13.9239 2.61736C13.9996 2.80009 14.0194 3.00116 13.9808 3.19514C13.9422 3.38912 13.8469 3.5673 13.7071 3.70715C13.5672 3.84701 13.3891 3.94225 13.1951 3.98083C13.0011 4.01942 12.8 3.99962 12.6173 3.92393C12.4346 3.84824 12.2784 3.72007 12.1685 3.55562C12.0586 3.39117 12 3.19783 12 3.00005C12.0003 2.73492 12.1057 2.48075 12.2932 2.29328C12.4807 2.10581 12.7349 2.00035 13 2.00005ZM1.99999 3.00005C1.99999 2.80227 2.05864 2.60893 2.16852 2.44448C2.2784 2.28003 2.43458 2.15186 2.6173 2.07617C2.80003 2.00048 3.0011 1.98068 3.19508 2.01926C3.38906 2.05785 3.56724 2.15309 3.70709 2.29294C3.84695 2.43279 3.94219 2.61098 3.98077 2.80496C4.01936 2.99894 3.99955 3.20001 3.92387 3.38273C3.84818 3.56546 3.72001 3.72164 3.55556 3.83152C3.39111 3.9414 3.19777 4.00005 2.99999 4.00005C2.73485 3.99978 2.48065 3.89434 2.29317 3.70686C2.10569 3.51938 2.00025 3.26518 1.99999 3.00005ZM2.99999 14C2.80221 14 2.60887 13.9414 2.44442 13.8315C2.27997 13.7216 2.15179 13.5655 2.07611 13.3827C2.00042 13.2 1.98062 12.9989 2.0192 12.805C2.05779 12.611 2.15303 12.4328 2.29288 12.2929C2.43273 12.1531 2.61092 12.0578 2.8049 12.0193C2.99888 11.9807 3.19994 12.0005 3.38267 12.0762C3.5654 12.1519 3.72158 12.28 3.83146 12.4445C3.94134 12.6089 3.99999 12.8023 3.99999 13C3.99968 13.2652 3.89423 13.5193 3.70676 13.7068C3.51929 13.8943 3.26511 13.9997 2.99999 14ZM11.071 12.5H4.92899C4.83944 12.1563 4.6598 11.8426 4.40861 11.5914C4.15741 11.3402 3.84376 11.1606 3.49999 11.071V4.92905C3.84373 4.83945 4.15737 4.6598 4.40855 4.40861C4.65974 4.15743 4.83939 3.84379 4.92899 3.50005H11.071C11.1605 3.84382 11.3402 4.15748 11.5914 4.40867C11.8426 4.65986 12.1562 4.8395 12.5 4.92905V11.071C12.1562 11.1606 11.8425 11.3402 11.5913 11.5914C11.3401 11.8426 11.1605 12.1563 11.071 12.5ZM13 14C12.8022 14 12.6089 13.9414 12.4444 13.8315C12.28 13.7216 12.1518 13.5655 12.0761 13.3827C12.0004 13.2 11.9806 12.9989 12.0192 12.805C12.0578 12.611 12.153 12.4328 12.2929 12.2929C12.4327 12.1531 12.6109 12.0578 12.8049 12.0193C12.9989 11.9807 13.1999 12.0005 13.3827 12.0762C13.5654 12.1519 13.7216 12.28 13.8315 12.4445C13.9413 12.6089 14 12.8023 14 13C13.9996 13.2652 13.8942 13.5193 13.7067 13.7068C13.5192 13.8942 13.2651 13.9997 13 14Z" fill="#161616"/>
79
+ </svg>
80
+
81
+
82
+ SVG XML Sample in IBM design style:
83
+
84
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
85
+ <rect width="16" height="16" fill="white" fill-opacity="0.01" style="mix-blend-mode:multiply"/>
86
+ <path d="M8 1C6.61553 1 5.26216 1.41054 4.11101 2.17971C2.95987 2.94888 2.06266 4.04213 1.53285 5.32122C1.00303 6.6003 0.86441 8.00777 1.13451 9.36563C1.4046 10.7235 2.07129 11.9708 3.05026 12.9497C4.02922 13.9287 5.2765 14.5954 6.63437 14.8655C7.99224 15.1356 9.3997 14.997 10.6788 14.4672C11.9579 13.9373 13.0511 13.0401 13.8203 11.889C14.5895 10.7378 15 9.38447 15 8C14.9979 6.14413 14.2597 4.36486 12.9474 3.05256C11.6351 1.74026 9.85588 1.00209 8 1V1ZM13.9746 7.5H11.0205C11.1458 6.20609 11.6189 4.97021 12.3897 3.92335C13.3047 4.9037 13.863 6.1636 13.9746 7.5V7.5ZM8.5 7.5V2.0254C9.64338 2.12054 10.735 2.54373 11.6437 3.24415C10.7081 4.47913 10.1448 5.95567 10.02 7.5H8.5ZM7.5 7.5H5.98C5.85523 5.95567 5.2919 4.47913 4.3563 3.24415C5.26503 2.54373 6.35663 2.12054 7.5 2.0254V7.5ZM7.5 8.5V13.9746C6.35663 13.8795 5.26503 13.4563 4.3563 12.7558C5.2919 11.5209 5.85523 10.0443 5.98 8.5H7.5ZM8.5 8.5H10.02C10.1448 10.0443 10.7082 11.5209 11.6438 12.7558C10.7351 13.4563 9.64341 13.8795 8.5 13.9746V8.5ZM3.61035 3.92335C4.38106 4.97021 4.85416 6.20609 4.9795 7.5H2.0254C2.13698 6.1636 2.69529 4.9037 3.61035 3.92335V3.92335ZM2.0254 8.5H4.9795C4.85416 9.79391 4.38106 11.0298 3.61035 12.0766C2.69529 11.0963 2.13698 9.8364 2.0254 8.5V8.5ZM12.3897 12.0766C11.6189 11.0298 11.1458 9.79391 11.0205 8.5H13.9746C13.863 9.8364 13.3047 11.0963 12.3897 12.0766V12.0766Z" fill="#161616"/>
87
+ </svg>
88
+
89
+
90
+ SVG XML in IBM design style:
91
+
92
+ """,
93
+ "display": False,
94
+ "example": "Tree dots",
95
+ "primer": '<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg"',
96
+ },
97
+ }
98
+
99
+
100
+ def list_prompts():
101
+ prompt_list = [k for k, v in svg_prompts.items() if v["display"] is True]
102
+ return prompt_list
103
+
104
+
105
+ def get_prompt_template(promptid):
106
+ return svg_prompts[promptid]["template"]
107
+
108
+
109
+ def get_prompt_example(promptid):
110
+ return svg_prompts[promptid]["example"]
111
+
112
+
113
+ def get_prompt_primer(promptid):
114
+ return svg_prompts[promptid]["primer"]
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio
2
+ ibm_watsonx_ai
svg_utils.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Remi Serra 202407
2
+
3
+ import base64
4
+ import xml.dom.minidom
5
+
6
+
7
+ def decode_b64_string_to_pretty_xml(encoded_string):
8
+ # split
9
+ split = encoded_string.split(",")
10
+ if len(split) > 1:
11
+ encoded = split[1]
12
+ else:
13
+ encoded = encoded_string
14
+ # decode
15
+ decoded_xml = base64.b64decode(encoded).decode("utf-8")
16
+
17
+ # pretify XML
18
+ dom = xml.dom.minidom.parseString(decoded_xml)
19
+ pretty_xml_as_string = dom.toprettyxml(indent="", newl="")
20
+ return pretty_xml_as_string
21
+
22
+
23
+ def encode_svg_xml_to_b64_string(svg_xml):
24
+ xml_b64 = base64.b64encode(svg_xml.encode("utf-8")).decode("utf-8")
25
+ # print(f"encode_svg_xml_to_b64_string:xml_b64:{xml_b64}")
26
+ return xml_b64
watsonx_utils.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Remi Serra 202407
2
+ from ibm_watsonx_ai import APIClient, Credentials
3
+ from ibm_watsonx_ai.metanames import GenTextParamsMetaNames
4
+ from ibm_watsonx_ai.foundation_models import Model
5
+
6
+
7
+ class wxEngine:
8
+
9
+ def __init__(self, apiendpoint, apikey, projectid):
10
+ # https://ibm.github.io/watsonx-ai-python-sdk/base.html#credentials.Credentials
11
+ self.credentials = Credentials(url=apiendpoint, api_key=apikey)
12
+ self.projectid = projectid
13
+ self.client = APIClient(credentials=self.credentials, project_id=self.projectid)
14
+ self.model = None
15
+
16
+ def init_model(self, modelid):
17
+ if self.model is None or (
18
+ modelid is not None and modelid != self.model.model_id
19
+ ):
20
+ self.model = Model(
21
+ model_id=modelid,
22
+ params={},
23
+ credentials=self.credentials,
24
+ project_id=self.projectid,
25
+ )
26
+ return self.model
27
+
28
+ def list_models(self):
29
+ TextModels_enum = self.client.foundation_models.TextModels
30
+ model_ids = [e.value for e in TextModels_enum]
31
+ # print(f"list_models:models:{models}")
32
+ return model_ids
33
+
34
+ def get_model_max_tokens(self, modelid):
35
+ model_specs = self.client.foundation_models.get_model_specs(model_id=modelid)
36
+ # print(f"get_model_specs:model_specs:{model_specs}")
37
+ max_tokens = model_specs["model_limits"]["max_sequence_length"]
38
+ print(f"get_model_specs:max_tokens:{max_tokens}")
39
+ return max_tokens
40
+
41
+ def get_prompt_nb_tokens(self, prompt, modelid):
42
+ # https://ibm.github.io/watson-machine-learning-sdk/model.html#ibm_watson_machine_learning.foundation_models.Model.tokenize
43
+ self.init_model(modelid)
44
+ prompt_embeddings = self.model.tokenize(prompt, return_tokens=False)
45
+ # print(f"get_prompt_nb_tokens:prompt_embeddings:{prompt_embeddings}")
46
+ prompt_len = prompt_embeddings["result"]["token_count"]
47
+ print(f"get_prompt_nb_tokens:prompt_len:{prompt_len}")
48
+ return prompt_len
49
+
50
+ def generate_text(
51
+ self,
52
+ prompt: str,
53
+ modelid=None,
54
+ decoding="greedy",
55
+ temperature=1.0,
56
+ seed=42,
57
+ min_new_tokens=50,
58
+ max_new_tokens=200,
59
+ stop_sequences=[],
60
+ repetition_penalty=1,
61
+ stream=False,
62
+ ):
63
+ self.init_model(modelid)
64
+ # Set the truncate_input_tokens to a value that is equal to or less than the maximum allowed tokens for the model that you are using. If you don't specify this value and the input has more tokens than the model can process, an error is generated.
65
+ truncate_input_tokens = int(self.get_model_max_tokens(modelid) * 0.9)
66
+ wmlparams = {
67
+ GenTextParamsMetaNames.DECODING_METHOD: decoding,
68
+ GenTextParamsMetaNames.TEMPERATURE: temperature,
69
+ GenTextParamsMetaNames.TOP_P: 0.2,
70
+ GenTextParamsMetaNames.TOP_K: 1,
71
+ GenTextParamsMetaNames.RANDOM_SEED: seed,
72
+ GenTextParamsMetaNames.MIN_NEW_TOKENS: min_new_tokens,
73
+ GenTextParamsMetaNames.MAX_NEW_TOKENS: max_new_tokens,
74
+ GenTextParamsMetaNames.STOP_SEQUENCES: stop_sequences,
75
+ GenTextParamsMetaNames.REPETITION_PENALTY: repetition_penalty,
76
+ GenTextParamsMetaNames.TRUNCATE_INPUT_TOKENS: truncate_input_tokens,
77
+ }
78
+ if stream:
79
+ return self.model.generate_text_stream(prompt, wmlparams)
80
+ else:
81
+ return self.model.generate_text(prompt, wmlparams)
82
+
83
+
84
+ ## TEST
85
+ if __name__ == "__main__":
86
+ engine = wxEngine(
87
+ "https://us-south.ml.cloud.ibm.com", "xxx_apikey_xxxx", "xxxx-projectid-xxxx"
88
+ )
89
+ print(f"Test generate: {engine.generate_text('Who is Einstein ?')}")
90
+ print(
91
+ f"Test generate_stream: {engine.generate_text('Who is Einstein ?', stream=True)}"
92
+ )