Spaces:
Paused
Paused
Improve guidance_prompt. Cleanup code
Browse files
app.py
CHANGED
|
@@ -23,6 +23,8 @@ from langchain_core.vectorstores import VectorStoreRetriever
|
|
| 23 |
|
| 24 |
import time
|
| 25 |
|
|
|
|
|
|
|
| 26 |
|
| 27 |
# feature_text = "Brand: Duckly. \nProduct name: Duck runner pro. \nKey properties: t-shirt, for running, sweat wicking, for marathon, 100% cotton."
|
| 28 |
|
|
@@ -105,6 +107,184 @@ models = ["gpt-4-turbo",
|
|
| 105 |
|
| 106 |
openai.api_key = os.environ["OPENAI_API_KEY"]
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
|
| 109 |
import base64
|
| 110 |
import requests
|
|
@@ -239,16 +419,17 @@ def get_language(struct_lang, copy_lang):
|
|
| 239 |
return "English"
|
| 240 |
|
| 241 |
|
| 242 |
-
def post_process(text: str, guidance_prompt: str, chat: ChatOpenAI):
|
| 243 |
messages = [
|
| 244 |
-
SystemMessage(content=f"""You are a helpful assistant that edit documents based on the guidlines provided. Make sure to write in
|
| 245 |
HumanMessage(content=f"""Given the following product description, your task is to
|
| 246 |
make minimal modification to the product description such that the resulting description
|
| 247 |
follows the rules defined in the guidlines. Make sure to preserve the structure of the
|
| 248 |
original text as much as possible. Do not modify the structure of the original text.
|
|
|
|
| 249 |
Output only the modified text in markdown format.
|
| 250 |
|
| 251 |
-
|
| 252 |
{text}
|
| 253 |
|
| 254 |
Guildlines:
|
|
@@ -323,7 +504,7 @@ def generate(*data):
|
|
| 323 |
print("visible", visible)
|
| 324 |
|
| 325 |
nargs = 11
|
| 326 |
-
feature, image, garment_type, model, temperature, nversions,
|
| 327 |
struct_ref = data[nargs:]
|
| 328 |
|
| 329 |
print(f"{feature=}")
|
|
@@ -331,8 +512,8 @@ def generate(*data):
|
|
| 331 |
print(f"{garment_type=}")
|
| 332 |
print(f"{model=}")
|
| 333 |
print(f"{temperature=}")
|
| 334 |
-
print(f"{
|
| 335 |
-
print(f"{
|
| 336 |
print(f"{debug=}")
|
| 337 |
# print(f"{glossary=}")
|
| 338 |
print(f"{glossary_upload=}")
|
|
@@ -357,12 +538,15 @@ def generate(*data):
|
|
| 357 |
detected_features = ""
|
| 358 |
intended_use = ""
|
| 359 |
alt_texts = []
|
|
|
|
| 360 |
if image_features is not None and len(image_features) > 0:
|
| 361 |
alt_texts = image_features["alt_text"]
|
| 362 |
detected_features = ", ".join(image_features["features"])
|
| 363 |
intended_use = ", ".join(image_features["intended_use"])
|
| 364 |
print(f"Detected features: {detected_features}, Intended use: {intended_use}, Alt text: {alt_texts}")
|
| 365 |
|
|
|
|
|
|
|
| 366 |
# if glossary:
|
| 367 |
# print("Getting terms")
|
| 368 |
# terms = glossary.invoke(input=feature + detected_features)
|
|
@@ -381,131 +565,14 @@ def generate(*data):
|
|
| 381 |
print("Using both copy and structure")
|
| 382 |
messages = [
|
| 383 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 384 |
-
HumanMessage(content=
|
| 385 |
-
Write in a way that target the customer.
|
| 386 |
-
For each version, write at least {min_length} words and at most {max_length} words.
|
| 387 |
-
Make sure that the structure of each output follows the reference structure. Do not add any additional sentences or structures that are not in the reference structure.
|
| 388 |
-
Make sure to use the tone of voice, rythm, cadence and style of the reference copy for each output.
|
| 389 |
-
Use markdown format for each output.
|
| 390 |
-
Do not include any part of the reference structure in the output.
|
| 391 |
-
The structure of the output should follow the reference structure.
|
| 392 |
-
Do not use the structure of the reference copy in the output.
|
| 393 |
-
Do not use any of the excluded words in the output.
|
| 394 |
-
Include all included words in the output.
|
| 395 |
-
Do not hallucinate any information.
|
| 396 |
-
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 397 |
-
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 398 |
-
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 399 |
-
For each version, try to write in different style.
|
| 400 |
-
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 401 |
-
Rate the quality of each version based on the following criteria:
|
| 402 |
-
- how well it follows the reference structure.
|
| 403 |
-
- how well it follows the tone of voice, rythm, cadence and style of the reference copy.
|
| 404 |
-
- how faithful it describes the product features.
|
| 405 |
-
- how well it avoid the excluded words.
|
| 406 |
-
- how well it includes the included words.
|
| 407 |
-
- how creative the language is.
|
| 408 |
-
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 409 |
-
Return the result in the following JSON format:
|
| 410 |
-
{{
|
| 411 |
-
"versions": [
|
| 412 |
-
{{
|
| 413 |
-
"id": 1,
|
| 414 |
-
"content": The first product description,
|
| 415 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 416 |
-
"score": The score of the first product description
|
| 417 |
-
}},
|
| 418 |
-
{{
|
| 419 |
-
"id": 2,
|
| 420 |
-
"content": The second product description,
|
| 421 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 422 |
-
"score": The score of the second product description
|
| 423 |
-
}},
|
| 424 |
-
...
|
| 425 |
-
],
|
| 426 |
-
"best_version": {{
|
| 427 |
-
"explanation": Explanation for why this version is the best,
|
| 428 |
-
"id": The id of the best version
|
| 429 |
-
}}
|
| 430 |
-
}}
|
| 431 |
-
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 432 |
-
|
| 433 |
-
Product information:
|
| 434 |
-
Key features: {feature}
|
| 435 |
-
{detected_features}
|
| 436 |
-
|
| 437 |
-
Intended use: {intended_use}
|
| 438 |
-
|
| 439 |
-
Reference structure: {structure}
|
| 440 |
-
|
| 441 |
-
Reference copy: {copy}
|
| 442 |
-
|
| 443 |
-
Included words: {included_words}
|
| 444 |
-
|
| 445 |
-
Excluded words: {excluded_words}"""),]
|
| 446 |
|
| 447 |
elif len(copy.strip()) > 0:
|
| 448 |
print('------------')
|
| 449 |
print("Using copy")
|
| 450 |
messages = [
|
| 451 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 452 |
-
HumanMessage(content=
|
| 453 |
-
Write in a way that target the customer.
|
| 454 |
-
For each version, write at least {min_length} words and at most {max_length} words.
|
| 455 |
-
Make sure that the structure of each output follows the structure of the reference copy.
|
| 456 |
-
Make sure to use the tone of voice, rythm, cadence and style of the reference copy for each output.
|
| 457 |
-
Use markdown format for each output.
|
| 458 |
-
Make sure that the structure of each output follows the structure of the reference copy.
|
| 459 |
-
Do not use any of the excluded words in the output.
|
| 460 |
-
Include all included words in the output.
|
| 461 |
-
Do not hallucinate any information.
|
| 462 |
-
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 463 |
-
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 464 |
-
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 465 |
-
For each version, try to write in different style.
|
| 466 |
-
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 467 |
-
Rate the quality of each version based on the following criteria:
|
| 468 |
-
- how well it follows the tone of voice, rythm, cadence and style of the reference copy.
|
| 469 |
-
- how faithful it describes the product features.
|
| 470 |
-
- how well it avoid the excluded words.
|
| 471 |
-
- how well it includes the included words.
|
| 472 |
-
- how creative the language is
|
| 473 |
-
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 474 |
-
Return the result in the following JSON format:
|
| 475 |
-
{{
|
| 476 |
-
"versions": [
|
| 477 |
-
{{
|
| 478 |
-
"id": 1,
|
| 479 |
-
"content": The first product description,
|
| 480 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 481 |
-
"score": The score of the first product description
|
| 482 |
-
}},
|
| 483 |
-
{{
|
| 484 |
-
"id": 2,
|
| 485 |
-
"content": The second product description,
|
| 486 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 487 |
-
"score": The score of the second product description
|
| 488 |
-
}},
|
| 489 |
-
...
|
| 490 |
-
],
|
| 491 |
-
"best_version": {{
|
| 492 |
-
"explanation": Explanation for why this version is the best,
|
| 493 |
-
"id": The id of the best version
|
| 494 |
-
}}
|
| 495 |
-
}}
|
| 496 |
-
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 497 |
-
|
| 498 |
-
Product information:
|
| 499 |
-
Key features: {feature}
|
| 500 |
-
{detected_features}
|
| 501 |
-
|
| 502 |
-
Intended use: {intended_use}
|
| 503 |
-
|
| 504 |
-
Reference copy: {copy}
|
| 505 |
-
|
| 506 |
-
Included words: {included_words}
|
| 507 |
-
|
| 508 |
-
Excluded words: {excluded_words}"""),]
|
| 509 |
print(messages[1].content)
|
| 510 |
print('------------')
|
| 511 |
|
|
@@ -514,63 +581,7 @@ Excluded words: {excluded_words}"""),]
|
|
| 514 |
print("Using structure")
|
| 515 |
messages = [
|
| 516 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 517 |
-
HumanMessage(content=
|
| 518 |
-
Write in a way that target the customer.
|
| 519 |
-
For each version, write at least {min_length} words and at most {max_length} words.
|
| 520 |
-
Make sure that the structure of each output follows the reference structure. Do not add any additional sentences or structures that are not in the reference structure.
|
| 521 |
-
Use markdown format for each output.
|
| 522 |
-
Do not include any part of the reference structure in the output.
|
| 523 |
-
Make sure that the structure of each output follows the reference structure.
|
| 524 |
-
Do not use any of the excluded words in the output.
|
| 525 |
-
Include all included words in the output.
|
| 526 |
-
Do not hallucinate any information.
|
| 527 |
-
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 528 |
-
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 529 |
-
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 530 |
-
For each version, try to write in different style.
|
| 531 |
-
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 532 |
-
Rate the quality of each version based on the following criteria:
|
| 533 |
-
- how well it follows the reference structure.
|
| 534 |
-
- how faithful it describes the product features.
|
| 535 |
-
- how well it avoid the excluded words.
|
| 536 |
-
- how well it includes the included words.
|
| 537 |
-
- how creative the language is.
|
| 538 |
-
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 539 |
-
Return the result in the following JSON format:
|
| 540 |
-
{{
|
| 541 |
-
"versions": [
|
| 542 |
-
{{
|
| 543 |
-
"id": 1,
|
| 544 |
-
"content": The first product description,
|
| 545 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 546 |
-
"score": The score of the first product description
|
| 547 |
-
}},
|
| 548 |
-
{{
|
| 549 |
-
"id": 2,
|
| 550 |
-
"content": The second product description,
|
| 551 |
-
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 552 |
-
"score": The score of the second product description
|
| 553 |
-
}},
|
| 554 |
-
...
|
| 555 |
-
],
|
| 556 |
-
"best_version": {{
|
| 557 |
-
"explanation": Explanation for why this version is the best,
|
| 558 |
-
"id": The id of the best version
|
| 559 |
-
}}
|
| 560 |
-
}}
|
| 561 |
-
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 562 |
-
|
| 563 |
-
Product information:
|
| 564 |
-
Key features: {feature}
|
| 565 |
-
{detected_features}
|
| 566 |
-
|
| 567 |
-
Intended use: {intended_use}
|
| 568 |
-
|
| 569 |
-
Reference structure: {structure}
|
| 570 |
-
|
| 571 |
-
Included words: {included_words}
|
| 572 |
-
|
| 573 |
-
Excluded words: {excluded_words}"""),]
|
| 574 |
print(messages[1].content)
|
| 575 |
print('------------')
|
| 576 |
batch.append(messages)
|
|
@@ -583,7 +594,8 @@ Excluded words: {excluded_words}"""),]
|
|
| 583 |
parser = JsonOutputParser()
|
| 584 |
jresponse = [parser.parse(msg.content) for msg in response]
|
| 585 |
descriptions = []
|
| 586 |
-
|
|
|
|
| 587 |
print(f'{jr=}')
|
| 588 |
bestid = jr["best_version"]["id"]
|
| 589 |
for d in jr["versions"]:
|
|
@@ -604,14 +616,17 @@ Excluded words: {excluded_words}"""),]
|
|
| 604 |
# bests = d["score"]
|
| 605 |
# bestd = d["content"] + (f"\n\nDebug info:\n\nScore: {d['score']}\n\nExplanation: {d['explanation']}" if debug else "")
|
| 606 |
# break
|
|
|
|
|
|
|
| 607 |
|
| 608 |
descriptions.append(bestd)
|
|
|
|
| 609 |
|
| 610 |
-
print("\n\nRewriting with glossary")
|
| 611 |
-
rewrite = glossary_rewrite(chat=chat, glossary=glossary, text=descriptions[0])
|
| 612 |
-
if rewrite != "":
|
| 613 |
-
|
| 614 |
-
print("\n\nDone rewriting with glossary\n\n")
|
| 615 |
|
| 616 |
md_content = "\n\n---\n\n".join(descriptions)
|
| 617 |
|
|
@@ -620,9 +635,9 @@ Excluded words: {excluded_words}"""),]
|
|
| 620 |
alt_text_dict = {k[0]: v for (k, v) in zip(image, alt_texts)} if len(alt_texts) > 0 else {}
|
| 621 |
result_json = {"outputs": jresponse if debug else descriptions, "alt_text": alt_text_dict}
|
| 622 |
|
| 623 |
-
post_content = post_process(text=md_content, guidance_prompt=guidance_prompt, chat=chat)
|
| 624 |
|
| 625 |
-
result_md = "Original\n\n" + md_content + "\n\n---\n\nModified\n\n" +
|
| 626 |
+ alt_texts_str \
|
| 627 |
+ '\n'.join([f'' if base64_image != "" else "" for (base64_image, alt_text) in zip(base64_images, alt_texts)])
|
| 628 |
|
|
@@ -681,8 +696,8 @@ with gr.Blocks() as demo:
|
|
| 681 |
model = gr.Dropdown(models, value="claude-3-5-sonnet-20241022", interactive=True, label="Model", visible=True)
|
| 682 |
temperature = gr.Slider(minimum=0., maximum=1.0, value=0., interactive=True, label="Temperature", visible=True)
|
| 683 |
nversions = gr.Slider(minimum=1, maximum=10, value=5, step=int, interactive=True, label="Number of versions", visible=True)
|
| 684 |
-
|
| 685 |
-
|
| 686 |
# glossary = gr.Dataframe(row_count = (2, "dynamic"), col_count=(2,"static"), headers=["Description", "Way of writing"], label="Glossary", interactive=True)
|
| 687 |
glossary_upload = gr.UploadButton(label="Upload Glossary", interactive=True, file_types=["csv"])
|
| 688 |
debug = gr.Checkbox(label="Debug", interactive=True, value=True)
|
|
@@ -708,7 +723,7 @@ with gr.Blocks() as demo:
|
|
| 708 |
md_output = gr.Markdown(label="Output", show_label=True, line_breaks=True)
|
| 709 |
json_output = gr.JSON(label="JSON Output")
|
| 710 |
submit.click(generate, inputs=[feature, image, garment_type, model, temperature, nversions,
|
| 711 |
-
|
| 712 |
outputs=[md_output, json_output])
|
| 713 |
# advanced.click(show_advanced, inputs=[], outputs=[model, temperature])
|
| 714 |
|
|
@@ -731,4 +746,8 @@ def authf(username, password):
|
|
| 731 |
|
| 732 |
if __name__ == '__main__':
|
| 733 |
# demo.launch(server_name="0.0.0.0", auth=authf)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
demo.launch()
|
|
|
|
| 23 |
|
| 24 |
import time
|
| 25 |
|
| 26 |
+
from str2escaped import str2escaped
|
| 27 |
+
|
| 28 |
|
| 29 |
# feature_text = "Brand: Duckly. \nProduct name: Duck runner pro. \nKey properties: t-shirt, for running, sweat wicking, for marathon, 100% cotton."
|
| 30 |
|
|
|
|
| 107 |
|
| 108 |
openai.api_key = os.environ["OPENAI_API_KEY"]
|
| 109 |
|
| 110 |
+
struct_copy_prompt = """Generate {nversions} versions of the product description for a product with the following information.
|
| 111 |
+
Write in a way that target the customer.
|
| 112 |
+
For each version, write at least {min_length} words and at most {max_length} words.
|
| 113 |
+
Make sure that the structure of each output follows the reference structure. Do not add any additional sentences or structures that are not in the reference structure.
|
| 114 |
+
Make sure to use the tone of voice, rythm, cadence and style of the reference copy for each output.
|
| 115 |
+
Use markdown format for each output.
|
| 116 |
+
Do not include any part of the reference structure in the output.
|
| 117 |
+
The structure of the output should follow the reference structure.
|
| 118 |
+
Do not use the structure of the reference copy in the output.
|
| 119 |
+
Do not use any of the excluded words in the output.
|
| 120 |
+
Include all included words in the output.
|
| 121 |
+
Make sure to use product features and intended use in the output.
|
| 122 |
+
Do not hallucinate any information about the product, use only the provided key features and intended use to write about the product.
|
| 123 |
+
Note that the reference copy should be used for style and tone only, do not use any part of the reference copy in the output.
|
| 124 |
+
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 125 |
+
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 126 |
+
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 127 |
+
For each version, try to write in different style.
|
| 128 |
+
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 129 |
+
Rate the quality of each version based on the following criteria:
|
| 130 |
+
- how faithful it describes the product features.
|
| 131 |
+
- how well it follows the reference structure.
|
| 132 |
+
- how well it follows the tone of voice, rythm, cadence and style of the reference copy.
|
| 133 |
+
- how well it avoid the excluded words.
|
| 134 |
+
- how well it includes the included words.
|
| 135 |
+
- how creative the language is.
|
| 136 |
+
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 137 |
+
Return the result in the following JSON format:
|
| 138 |
+
{{
|
| 139 |
+
"versions": [
|
| 140 |
+
{{
|
| 141 |
+
"id": 1,
|
| 142 |
+
"content": The first product description,
|
| 143 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 144 |
+
"score": The score of the first product description
|
| 145 |
+
}},
|
| 146 |
+
{{
|
| 147 |
+
"id": 2,
|
| 148 |
+
"content": The second product description,
|
| 149 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 150 |
+
"score": The score of the second product description
|
| 151 |
+
}},
|
| 152 |
+
...
|
| 153 |
+
],
|
| 154 |
+
"best_version": {{
|
| 155 |
+
"explanation": Explanation for why this version is the best,
|
| 156 |
+
"id": The id of the best version
|
| 157 |
+
}}
|
| 158 |
+
}}
|
| 159 |
+
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 160 |
+
|
| 161 |
+
Product information:
|
| 162 |
+
Key features: {key_features}
|
| 163 |
+
|
| 164 |
+
Reference structure: {structure}
|
| 165 |
+
|
| 166 |
+
Reference copy: {copy}
|
| 167 |
+
|
| 168 |
+
Included words: {included_phrases}
|
| 169 |
+
|
| 170 |
+
Excluded words: {excluded_phrases}"""
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
copy_prompt = """Generate {nversions} versions of the product description for a product with the following information.
|
| 174 |
+
Write in a way that target the customer.
|
| 175 |
+
For each version, write at least {min_length} words and at most {max_length} words.
|
| 176 |
+
Make sure that the structure of each output follows the structure of the reference copy.
|
| 177 |
+
Make sure to use the tone of voice, rythm, cadence and style of the reference copy for each output.
|
| 178 |
+
Use markdown format for each output.
|
| 179 |
+
Make sure that the structure of each output follows the structure of the reference copy.
|
| 180 |
+
Do not use any of the excluded words in the output.
|
| 181 |
+
Include all included words in the output.
|
| 182 |
+
Make sure to use product features and intended use in the output.
|
| 183 |
+
Do not hallucinate any information about the product, use only the provided key features and intended use to write about the product.
|
| 184 |
+
Note that the reference copy should be used for style and tone only, do not use any part of the reference copy in the output.
|
| 185 |
+
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 186 |
+
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 187 |
+
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 188 |
+
For each version, try to write in different style.
|
| 189 |
+
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 190 |
+
Rate the quality of each version based on the following criteria:
|
| 191 |
+
- how faithful it describes the product features.
|
| 192 |
+
- how well it follows the tone of voice, rythm, cadence and style of the reference copy.
|
| 193 |
+
- how well it avoid the excluded words.
|
| 194 |
+
- how well it includes the included words.
|
| 195 |
+
- how creative the language is
|
| 196 |
+
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 197 |
+
Return the result in the following JSON format:
|
| 198 |
+
{{
|
| 199 |
+
"versions": [
|
| 200 |
+
{{
|
| 201 |
+
"id": 1,
|
| 202 |
+
"content": The first product description,
|
| 203 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 204 |
+
"score": The score of the first product description
|
| 205 |
+
}},
|
| 206 |
+
{{
|
| 207 |
+
"id": 2,
|
| 208 |
+
"content": The second product description,
|
| 209 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 210 |
+
"score": The score of the second product description
|
| 211 |
+
}},
|
| 212 |
+
...
|
| 213 |
+
],
|
| 214 |
+
"best_version": {{
|
| 215 |
+
"explanation": Explanation for why this version is the best,
|
| 216 |
+
"id": The id of the best version
|
| 217 |
+
}}
|
| 218 |
+
}}
|
| 219 |
+
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 220 |
+
|
| 221 |
+
Product information:
|
| 222 |
+
Key features: {key_features}
|
| 223 |
+
|
| 224 |
+
Reference copy: {copy}
|
| 225 |
+
|
| 226 |
+
Included words: {included_phrases}
|
| 227 |
+
|
| 228 |
+
Excluded words: {excluded_phrases}"""
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
struct_prompt = """Generate {nversions} versions of the product description for a product with the following information.
|
| 232 |
+
Write in a way that target the customer.
|
| 233 |
+
For each version, write at least {min_length} words and at most {max_length} words.
|
| 234 |
+
Make sure that the structure of each output follows the reference structure. Do not add any additional sentences or structures that are not in the reference structure.
|
| 235 |
+
Use markdown format for each output.
|
| 236 |
+
Do not include any part of the reference structure in the output.
|
| 237 |
+
Make sure that the structure of each output follows the reference structure.
|
| 238 |
+
Do not use any of the excluded words in the output.
|
| 239 |
+
Include all included words in the output.
|
| 240 |
+
Make sure to use product features and intended use in the output.
|
| 241 |
+
Do not hallucinate any information about the product, use only the provided key features and intended use to write about the product.
|
| 242 |
+
Note that the reference structure should be used for structure only, do not use any part of the reference structure in the output.
|
| 243 |
+
Do not hallucinate information about size and weight. Write about size and weight only if it is available in the list of features.
|
| 244 |
+
Use creative language in each output, do not use the common ways of starting product descriptions.
|
| 245 |
+
Avoid common phrases and cliches such as "Step into something", "Elevate something", "Discover something", "Unleash something", "Embrace something", and similar phrases.
|
| 246 |
+
For each version, try to write in different style.
|
| 247 |
+
Put each item in the list on a separate line. Use '-' character to start each item.
|
| 248 |
+
Rate the quality of each version based on the following criteria:
|
| 249 |
+
- how faithful it describes the product features.
|
| 250 |
+
- how well it follows the reference structure.
|
| 251 |
+
- how well it avoid the excluded words.
|
| 252 |
+
- how well it includes the included words.
|
| 253 |
+
- how creative the language is.
|
| 254 |
+
The score should be a number between 0 and 10 with 10 being the best quality.
|
| 255 |
+
Return the result in the following JSON format:
|
| 256 |
+
{{
|
| 257 |
+
"versions": [
|
| 258 |
+
{{
|
| 259 |
+
"id": 1,
|
| 260 |
+
"content": The first product description,
|
| 261 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 262 |
+
"score": The score of the first product description
|
| 263 |
+
}},
|
| 264 |
+
{{
|
| 265 |
+
"id": 2,
|
| 266 |
+
"content": The second product description,
|
| 267 |
+
"explanation": A less than 20 word explanation of the score of the first product description,
|
| 268 |
+
"score": The score of the second product description
|
| 269 |
+
}},
|
| 270 |
+
...
|
| 271 |
+
],
|
| 272 |
+
"best_version": {{
|
| 273 |
+
"explanation": Explanation for why this version is the best,
|
| 274 |
+
"id": The id of the best version
|
| 275 |
+
}}
|
| 276 |
+
}}
|
| 277 |
+
Make sure that the output is in JSON format, no extra text should be included in the output.
|
| 278 |
+
|
| 279 |
+
Product information:
|
| 280 |
+
Key features: {key_features}
|
| 281 |
+
|
| 282 |
+
Reference structure: {structure}
|
| 283 |
+
|
| 284 |
+
Included words: {included_phrases}
|
| 285 |
+
|
| 286 |
+
Excluded words: {excluded_phrases}"""
|
| 287 |
+
|
| 288 |
|
| 289 |
import base64
|
| 290 |
import requests
|
|
|
|
| 419 |
return "English"
|
| 420 |
|
| 421 |
|
| 422 |
+
def post_process(text: str, guidance_prompt: str, language: str, chat: ChatOpenAI):
|
| 423 |
messages = [
|
| 424 |
+
SystemMessage(content=f"""You are a helpful assistant that edit documents based on the guidlines provided. Make sure to write in {language} language."""),
|
| 425 |
HumanMessage(content=f"""Given the following product description, your task is to
|
| 426 |
make minimal modification to the product description such that the resulting description
|
| 427 |
follows the rules defined in the guidlines. Make sure to preserve the structure of the
|
| 428 |
original text as much as possible. Do not modify the structure of the original text.
|
| 429 |
+
Do not change the language of the original text.
|
| 430 |
Output only the modified text in markdown format.
|
| 431 |
|
| 432 |
+
Product description:
|
| 433 |
{text}
|
| 434 |
|
| 435 |
Guildlines:
|
|
|
|
| 504 |
print("visible", visible)
|
| 505 |
|
| 506 |
nargs = 11
|
| 507 |
+
feature, image, garment_type, model, temperature, nversions, excluded_phrases, included_phrases, glossary_upload, debug, guidance_prompt = data[:nargs]
|
| 508 |
struct_ref = data[nargs:]
|
| 509 |
|
| 510 |
print(f"{feature=}")
|
|
|
|
| 512 |
print(f"{garment_type=}")
|
| 513 |
print(f"{model=}")
|
| 514 |
print(f"{temperature=}")
|
| 515 |
+
print(f"{excluded_phrases=}")
|
| 516 |
+
print(f"{included_phrases=}")
|
| 517 |
print(f"{debug=}")
|
| 518 |
# print(f"{glossary=}")
|
| 519 |
print(f"{glossary_upload=}")
|
|
|
|
| 538 |
detected_features = ""
|
| 539 |
intended_use = ""
|
| 540 |
alt_texts = []
|
| 541 |
+
key_features = feature
|
| 542 |
if image_features is not None and len(image_features) > 0:
|
| 543 |
alt_texts = image_features["alt_text"]
|
| 544 |
detected_features = ", ".join(image_features["features"])
|
| 545 |
intended_use = ", ".join(image_features["intended_use"])
|
| 546 |
print(f"Detected features: {detected_features}, Intended use: {intended_use}, Alt text: {alt_texts}")
|
| 547 |
|
| 548 |
+
key_features = key_features + ", " + detected_features + "\nIntended uses: " + intended_use
|
| 549 |
+
|
| 550 |
# if glossary:
|
| 551 |
# print("Getting terms")
|
| 552 |
# terms = glossary.invoke(input=feature + detected_features)
|
|
|
|
| 565 |
print("Using both copy and structure")
|
| 566 |
messages = [
|
| 567 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 568 |
+
HumanMessage(content=struct_copy_prompt.format(nversions=nversions, min_length=min_length, max_length=max_length, key_features=key_features, structure=structure, copy=copy, included_phrases=included_phrases, excluded_phrases=excluded_phrases)),]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
|
| 570 |
elif len(copy.strip()) > 0:
|
| 571 |
print('------------')
|
| 572 |
print("Using copy")
|
| 573 |
messages = [
|
| 574 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 575 |
+
HumanMessage(content=copy_prompt.format(nversions=nversions, min_length=min_length, max_length=max_length, key_features=key_features, structure=structure, copy=copy, included_phrases=included_phrases, excluded_phrases=excluded_phrases)),]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
print(messages[1].content)
|
| 577 |
print('------------')
|
| 578 |
|
|
|
|
| 581 |
print("Using structure")
|
| 582 |
messages = [
|
| 583 |
SystemMessage(content=f"""You are a helpful assistant that writes about products for ecommerce websites. Make sure to write in {languages[i]} language."""),
|
| 584 |
+
HumanMessage(content=struct_prompt.format(nversions=nversions, min_length=min_length, max_length=max_length, key_features=key_features, structure=structure, copy=copy, included_phrases=included_phrases, excluded_phrases=excluded_phrases)),]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
print(messages[1].content)
|
| 586 |
print('------------')
|
| 587 |
batch.append(messages)
|
|
|
|
| 594 |
parser = JsonOutputParser()
|
| 595 |
jresponse = [parser.parse(msg.content) for msg in response]
|
| 596 |
descriptions = []
|
| 597 |
+
descriptions_post = []
|
| 598 |
+
for i, jr in enumerate(jresponse):
|
| 599 |
print(f'{jr=}')
|
| 600 |
bestid = jr["best_version"]["id"]
|
| 601 |
for d in jr["versions"]:
|
|
|
|
| 616 |
# bests = d["score"]
|
| 617 |
# bestd = d["content"] + (f"\n\nDebug info:\n\nScore: {d['score']}\n\nExplanation: {d['explanation']}" if debug else "")
|
| 618 |
# break
|
| 619 |
+
|
| 620 |
+
bestd_post = post_process(text=bestd, guidance_prompt=guidance_prompt, language=languages[i], chat=chat)
|
| 621 |
|
| 622 |
descriptions.append(bestd)
|
| 623 |
+
descriptions_post.append(bestd_post)
|
| 624 |
|
| 625 |
+
# print("\n\nRewriting with glossary")
|
| 626 |
+
# rewrite = glossary_rewrite(chat=chat, glossary=glossary, text=descriptions[0])
|
| 627 |
+
# if rewrite != "":
|
| 628 |
+
# descriptions[0] = "Original:\n\n" + descriptions[0] + "\n\nRewritten:\n\n" + rewrite
|
| 629 |
+
# print("\n\nDone rewriting with glossary\n\n")
|
| 630 |
|
| 631 |
md_content = "\n\n---\n\n".join(descriptions)
|
| 632 |
|
|
|
|
| 635 |
alt_text_dict = {k[0]: v for (k, v) in zip(image, alt_texts)} if len(alt_texts) > 0 else {}
|
| 636 |
result_json = {"outputs": jresponse if debug else descriptions, "alt_text": alt_text_dict}
|
| 637 |
|
| 638 |
+
# post_content = post_process(text=md_content, guidance_prompt=guidance_prompt, language=languages, chat=chat)
|
| 639 |
|
| 640 |
+
result_md = "Original\n\n" + md_content + "\n\n---\n\nModified\n\n" + '\n'.join(descriptions_post) + "\n\n" \
|
| 641 |
+ alt_texts_str \
|
| 642 |
+ '\n'.join([f'' if base64_image != "" else "" for (base64_image, alt_text) in zip(base64_images, alt_texts)])
|
| 643 |
|
|
|
|
| 696 |
model = gr.Dropdown(models, value="claude-3-5-sonnet-20241022", interactive=True, label="Model", visible=True)
|
| 697 |
temperature = gr.Slider(minimum=0., maximum=1.0, value=0., interactive=True, label="Temperature", visible=True)
|
| 698 |
nversions = gr.Slider(minimum=1, maximum=10, value=5, step=int, interactive=True, label="Number of versions", visible=True)
|
| 699 |
+
excluded_phrases = gr.Textbox(label="Excluded words", interactive=True, lines=2)
|
| 700 |
+
included_phrases = gr.Textbox(label="Included words", interactive=True, lines=2)
|
| 701 |
# glossary = gr.Dataframe(row_count = (2, "dynamic"), col_count=(2,"static"), headers=["Description", "Way of writing"], label="Glossary", interactive=True)
|
| 702 |
glossary_upload = gr.UploadButton(label="Upload Glossary", interactive=True, file_types=["csv"])
|
| 703 |
debug = gr.Checkbox(label="Debug", interactive=True, value=True)
|
|
|
|
| 723 |
md_output = gr.Markdown(label="Output", show_label=True, line_breaks=True)
|
| 724 |
json_output = gr.JSON(label="JSON Output")
|
| 725 |
submit.click(generate, inputs=[feature, image, garment_type, model, temperature, nversions,
|
| 726 |
+
excluded_phrases, included_phrases, glossary_upload, debug, guidance_prompt, *struct_ref],
|
| 727 |
outputs=[md_output, json_output])
|
| 728 |
# advanced.click(show_advanced, inputs=[], outputs=[model, temperature])
|
| 729 |
|
|
|
|
| 746 |
|
| 747 |
if __name__ == '__main__':
|
| 748 |
# demo.launch(server_name="0.0.0.0", auth=authf)
|
| 749 |
+
with open("formatted_prompts.txt", "w") as f:
|
| 750 |
+
f.writelines('"write_struct_copy": "' + str2escaped(struct_copy_prompt).strip() + '",')
|
| 751 |
+
f.writelines('"write_copy": "' + str2escaped(copy_prompt).strip() + '",')
|
| 752 |
+
f.writelines('"write_struct": "' + str2escaped(struct_prompt).strip() + '",')
|
| 753 |
demo.launch()
|