tunght commited on
Commit
140a47c
·
1 Parent(s): 8a3c172
Files changed (2) hide show
  1. app.py +169 -0
  2. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import gradio as gr
3
+ import numpy as np
4
+ import os
5
+
6
+ from langchain.chat_models import ChatOpenAI
7
+ from langchain.schema import HumanMessage, SystemMessage, AIMessage
8
+ from langchain_anthropic import ChatAnthropic, ChatAnthropicMessages
9
+ import openai
10
+
11
+ os.environ["OPENAI_API_KEY"] = "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"
12
+ os.environ["ANTHROPIC_API_KEY"] = \
13
+ "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"
14
+ openai.api_key = os.environ["OPENAI_API_KEY"]
15
+ # chat = ChatOpenAI(model="gpt-4-turbo-preview")
16
+ # chat = ChatOpenAI(model="gpt-3.5-turbo")
17
+
18
+ structure = """
19
+ # Headline {{ headline | bold, inspiring, action-oriented, max 8 words }}
20
+
21
+ ## Introduction
22
+ {{ introduction_paragraph | motivational, passionate, 2-3 sentences }}
23
+
24
+ ## Features and Benefits
25
+ {% for feature in features %}
26
+ ### Feature {{ loop.index }}: {{ feature.name | dynamic, direct, 5-6 words }}
27
+ {{ feature.details | energetic, clear, 3-4 sentences }}
28
+ {% endfor %}
29
+
30
+ ## Technical Specifications
31
+ {{ technical_specs | informative, to the point, concise list format }}
32
+ """
33
+
34
+ features = "Brand: Duckly. \nProduct name: Duck runner pro. \nKey properties: t-shirt, for running, sweat wicking, for marathon, 100% cotton."
35
+
36
+ reference = " "
37
+
38
+ import base64
39
+ import requests
40
+
41
+ # OpenAI API Key
42
+
43
+ # Function to encode the image
44
+ def encode_image(image_path):
45
+ with open(image_path, "rb") as image_file:
46
+ return base64.b64encode(image_file.read()).decode('utf-8')
47
+
48
+
49
+ import json
50
+
51
+
52
+ def get_json(text: str):
53
+ text = text.strip().replace('`', '').replace('json', '')
54
+ if text.startswith("No garment detected"):
55
+ return {
56
+ "features": [],
57
+ "intended_use": [],
58
+ "alt_text": []
59
+ }
60
+ return json.loads(text)
61
+
62
+
63
+ def detect_features(image_paths):
64
+ # Path to your image
65
+ # image_path = "path_to_your_image.jpg"
66
+
67
+ # Getting the base64 string
68
+ try:
69
+ base64_images = [encode_image(image_path[0]) for image_path in image_paths]
70
+
71
+ headers = {
72
+ "Content-Type": "application/json",
73
+ "Authorization": f"Bearer {openai.api_key}"
74
+ }
75
+
76
+ payload = {
77
+ "model": "gpt-4-vision-preview",
78
+ "messages": [
79
+ {
80
+ "role": "user",
81
+ "content": [
82
+ {
83
+ "type": "text",
84
+ "text": """Describe the features of the garment in the photos in less than 100 words.
85
+ What is the intended use of the garment in this image, use at most 5 words for intended use?
86
+ Generate alt text for each of the images.
87
+ If the photo does not contain a garment, return 'No garment detected'.
88
+ If the photo contains a garment, return the result in in the following JSON format without any preceding or trailing text:
89
+ {
90
+ "features": [list of comma separated features],
91
+ "intended_use": [list of comma separated intended uses],
92
+ "alt_text": [alt text for image 1, alt text for image 2]
93
+ }"""
94
+ },
95
+ ] + [{
96
+ "type": "image_url",
97
+ "image_url": {
98
+ "url": f"data:image/jpeg;base64,{base64_image}"
99
+ }
100
+ } for base64_image in base64_images]
101
+ }
102
+ ],
103
+ "temperature": 0.0,
104
+ "max_tokens": 300
105
+ }
106
+
107
+ response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
108
+
109
+ response = response.json()
110
+ print("image features", response["choices"][0]['message']['content'])
111
+ jresponse = get_json(response["choices"][0]['message']['content'])
112
+ return jresponse, base64_images
113
+ except Exception as e:
114
+ print(e.__class__, e)
115
+ traceback.print_exc()
116
+ return None, None
117
+
118
+
119
+ def generate(features, image, structure, reference, model, temperature):
120
+ print(f"features {features},\n image {image},\n structure{structure},\n model{model},\n temperature {temperature},\n reference {reference}")
121
+ image_features, base64_images = detect_features(image)
122
+ detected_features = ""
123
+ intended_use = ""
124
+ alt_texts = ""
125
+ if image_features is not None:
126
+ alt_texts = image_features["alt_text"]
127
+ detected_features = ", ".join(image_features["features"])
128
+ intended_use = "Intended use: " + ", ".join(image_features["intended_use"])
129
+ print(f"Detected features: {detected_features}, Intended use: {intended_use}, Alt text: {alt_texts}")
130
+ if model.startswith("gpt"):
131
+ chat = ChatOpenAI(model=model)
132
+ else:
133
+ chat = ChatAnthropic(model_name=model, anthropic_api_key=os.environ["ANTHROPIC_API_KEY"])
134
+ messages = [HumanMessage(content=f"""Write a product description of about 200 words for a product with the following key properties.
135
+ Make sure that the description follows the structure of the reference structure below.
136
+ Use creative language that is suitable for e-commerce websites. Use a consistent tone of voice throughout the text.
137
+ If the reference text is not empty, produce the product description in the tone of voice and structure of the reference text.
138
+ \n\n {features + detected_features} \n{intended_use} \nReference structure: {structure}\n Reference text: {reference}""")]
139
+ chat_response = chat.invoke(messages, temperature=temperature)
140
+ print(messages[0].content)
141
+ return chat_response.content + '\n\n### Alt text\n\n' + '\n- ' + '\n- '.join(alt_texts) + '\n'.join([f'![Product photo](data:image/png;base64,{base64_image} "{alt_text}")' if base64_image != "" else "" for (base64_image, alt_text) in zip(base64_images, alt_texts)])
142
+
143
+
144
+ demo = gr.Interface(
145
+ fn=generate,
146
+ inputs=[gr.Textbox(features, label="Features"),
147
+ gr.Gallery(label="Product image", type="filepath"),
148
+ gr.Textbox(structure, label="Structure"),
149
+ gr.Textbox(reference, label="Reference copy"),
150
+ gr.Dropdown(["gpt-4-turbo", "gpt-3.5-turbo", "claude-3-sonnet-20240229", "claude-3-opus-20240229"], value="gpt-3.5-turbo", label="Model"),
151
+ gr.Slider(minimum=0., maximum=1.0, value=0.5, label="Temperature")],
152
+ outputs=["markdown"],
153
+ )
154
+
155
+ # demo.launch()
156
+
157
+ import argparse
158
+
159
+ parser = argparse.ArgumentParser(description='Run the Gradio demo')
160
+ parser.add_argument('--public', action='store_true', help='Expose the demo to the public')
161
+ args = parser.parse_args()
162
+
163
+ # if args.public:
164
+ # demo.launch(share=True)
165
+ # else:
166
+ # demo.launch(server_name="0.0.0.0", server_port=7868)
167
+
168
+ if __name__ == "__main__":
169
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ langchain
2
+ langchain_openai
3
+ langchain_anthropic
4
+ openai