thanhnt-cf commited on
Commit
7a38b33
·
1 Parent(s): 0755ce5

initial commit

Browse files
.gitignore ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # These are some examples of commonly ignored file patterns.
2
+ # You should customize this list as applicable to your project.
3
+ # Learn more about .gitignore:
4
+ # https://www.atlassian.com/git/tutorials/saving-changes/gitignore
5
+
6
+ # Node artifact files
7
+ node_modules/
8
+ dist/
9
+
10
+ # Compiled Java class files
11
+ *.class
12
+
13
+ # Compiled Python bytecode
14
+ *.py[cod]
15
+
16
+ # Log files
17
+ *.log
18
+
19
+ # Package files
20
+ *.jar
21
+
22
+ # Maven
23
+ target/
24
+ dist/
25
+
26
+ # JetBrains IDE
27
+ .idea/
28
+
29
+ # Unit test reports
30
+ TEST*.xml
31
+
32
+ # Generated by MacOS
33
+ .DS_Store
34
+
35
+ # Generated by Windows
36
+ Thumbs.db
37
+
38
+ # Applications
39
+ *.app
40
+ *.exe
41
+ *.war
42
+
43
+ # Large media files
44
+ *.mp4
45
+ *.tiff
46
+ *.avi
47
+ *.flv
48
+ *.mov
49
+ *.wmv
50
+
51
+ env/
52
+ __pycache__/
53
+ testcases/
54
+ *.ipynb
55
+ server.crt
56
+ server.key
57
+ server.csr
58
+ sample_data.json
app.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import gradio as gr
3
+ from dotenv import load_dotenv
4
+ from llm_api.exceptions import RefusalError
5
+ # from llm_api.langchain_api import extract_info, follow_structure
6
+ from llm_api.native_api import extract_info, follow_structure
7
+ from openai import BadRequestError
8
+
9
+ load_dotenv('.env', override=True)
10
+
11
+ def extract_free_fn(gallery, provider, schema):
12
+ img_paths = [item[0] for item in gallery]
13
+ # write schema to file before calling extract_free_properties
14
+ try:
15
+ if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
16
+ with open('schema_free.py', 'r') as f:
17
+ default_schema = f.read()
18
+ import_part = default_schema.split('#####')[0]
19
+ print('Executing freestyle schema...')
20
+ full_schema = import_part + schema
21
+ with open('read_schema_free.py', 'w') as f:
22
+ f.write(full_schema)
23
+ exec(import_part + schema, globals())
24
+ print('Executed freestyle schema')
25
+ else:
26
+ print('SCHEMA ELSE')
27
+ raise Exception('Invalid schema')
28
+ except Exception as e:
29
+ print(e)
30
+ return 'Invalid schema! Please check the schema or Reload this page to restore default settings', {}, []
31
+
32
+ try:
33
+ free_attributes = extract_info(img_paths, provider, Garment)
34
+ free_attributes = free_attributes.model_dump_json()
35
+ except RefusalError as e:
36
+ return e.message, {}, []
37
+ except BadRequestError as e:
38
+ return e.message, {}, []
39
+
40
+ return f'OK - provider: {provider}', free_attributes, [1] * 100
41
+
42
+ def follow_schema_fn(free_attributes, provider, probs, schema):
43
+ try:
44
+ if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
45
+ with open('schema_structured.py', 'r') as f:
46
+ default_schema = f.read()
47
+ import_part = default_schema.split('#####')[0]
48
+ print('executing structured schema\n')
49
+ full_schema = import_part + schema
50
+ with open('read_schema_structured.py', 'w') as f:
51
+ f.write(full_schema)
52
+ exec(full_schema, globals())
53
+ print('executed structured schema')
54
+ else:
55
+ print('SCHEMA ELSE')
56
+ raise Exception('Invalid schema')
57
+ except:
58
+ return 'Invalid schema! Please check the schema or Reload this page to restore default settings', {}
59
+
60
+ try:
61
+ schema_attributes = follow_structure(free_attributes, provider, Garment)
62
+ schema_attributes = schema_attributes.model_dump_json()
63
+ except RefusalError as e:
64
+ return e.message, {}
65
+ except BadRequestError as e:
66
+ return e.message, {}
67
+
68
+ return f'OK - provider: {provider}', schema_attributes
69
+
70
+ with gr.Blocks(title='Internal Demo for Attribution') as demo:
71
+ with gr.Row():
72
+ with gr.Column(scale=12):
73
+ gr.Markdown('''<div style="text-align: center; font-size: 24px;"><strong>Internal Demo for Attribution</strong></div>''')
74
+ with gr.Row():
75
+ with gr.Column(scale=4):
76
+ # gr.Markdown('''<div style="text-align: left; font-size: 18px;">Upload images of a garment and click Extract Freestyle</div>''')
77
+ gallery = gr.Gallery(label='Images', type='filepath')
78
+ probs_text = gr.Textbox(label='Probabilities', placeholder='Probabilities', visible=False)
79
+ provider = gr.Dropdown(label='Provider', choices=['openai', 'anthropic'], value='openai')
80
+ button_extract = gr.Button(value='Extract Freestyle')
81
+ with gr.Column(scale=4):
82
+ # gr.Markdown('''<div style="text-align: left; font-size: 18px;">Click Follow Schema to convert the freestyle output to predefined schema</div>''')
83
+ status_free_text = gr.Textbox(label='Request Status', placeholder='')
84
+ free_attributes = gr.JSON(label='Freestyle Attribute')
85
+ button_follow = gr.Button(value='Follow Schema')
86
+ with gr.Column(scale=4):
87
+ status_structured_text = gr.Textbox(label='Request Status', placeholder='')
88
+ schema_attributes = gr.JSON(label='Schema Attributes')
89
+ with gr.Row():
90
+ # free_schema = gr.Dataframe(row_count=(4, 'dynamic'), label='Freestyle Schema', col_count=(4, 'dynamic'), interactive=True)
91
+ # schema = gr.Dataframe(row_count=(4, 'dynamic'), label='Schema', col_count=(4, 'dynamic'), interactive=True)
92
+ with open('schema_free.py', 'r') as f:
93
+ schema_free_text = f.read()
94
+ schema_free_text = schema_free_text.split('#####')[1]
95
+ with open('schema_structured.py', 'r') as f:
96
+ schema_structured_text = f.read()
97
+ schema_structured_text = schema_structured_text.split('#####')[1]
98
+ free_schema = gr.TextArea(label='Freestyle Schema', placeholder='Freestyle Schema', visible=True, value=schema_free_text, interactive=True)
99
+ structured_schema = gr.TextArea(label='Structured Schema', placeholder='Schema', visible=True, value=schema_structured_text, interactive=True)
100
+
101
+ button_extract.click(extract_free_fn, [gallery, provider, free_schema], [status_free_text, free_attributes, probs_text])
102
+ button_follow.click(follow_schema_fn, [free_attributes, provider, probs_text, structured_schema], [status_structured_text, schema_attributes])
103
+
104
+ # demo.launch(server_name="0.0.0.0", server_port=7688, share=False, ssl_verify=True, ssl_certfile=None, ssl_keyfile=None, auth=None)
105
+ # demo.launch(server_name="0.0.0.0", server_port=7860, share=False, ssl_verify=False, ssl_certfile="server.crt", ssl_keyfile="server.key", auth=None)
106
+ demo.launch(server_name="0.0.0.0", server_port=7861)
107
+
llm_api/anthropic_api.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from anthropic import Anthropic
2
+ from dotenv import load_dotenv
3
+ from llm_api.utils import get_data_format, get_image_data
4
+ from .constants import EXTRACT_INFO_HUMAN_MESSAGE, EXTRACT_INFO_SYSTEM_MESSAGE,FOLLOW_SCHEMA_HUMAN_MESSAGE, FOLLOW_SCHEMA_SYSTEM_MESSAGE
5
+
6
+ load_dotenv(override=True)
7
+ client = Anthropic()
8
+
9
+ def extract_info(img_paths, schema):
10
+ print('Extracting info via Anthropic...')
11
+ tools = [
12
+ {
13
+ "name": "extract_garment_info",
14
+ "description": "Extracts key information from the image.",
15
+ "input_schema": schema.model_json_schema(),
16
+ "cache_control": {"type": "ephemeral"}
17
+ }
18
+ ]
19
+
20
+ image_messages = [
21
+ {
22
+ "type": "image",
23
+ "source": {
24
+ "type": "base64",
25
+ "media_type": f"image/{get_data_format(img_path)}",
26
+ "data": get_image_data(img_path)
27
+ }
28
+ } for img_path in img_paths
29
+ ]
30
+
31
+ system_message = [
32
+ {
33
+ "type": "text",
34
+ "text": EXTRACT_INFO_SYSTEM_MESSAGE
35
+ }
36
+ ]
37
+
38
+ text_messages = [{
39
+ "type": "text",
40
+ "text": EXTRACT_INFO_HUMAN_MESSAGE,
41
+ }]
42
+
43
+ messages=[
44
+ {
45
+ "role": "user",
46
+ "content": text_messages + image_messages
47
+ }
48
+ ]
49
+
50
+ response = client.messages.create(
51
+ model="claude-3-5-sonnet-20240620",
52
+ extra_headers={
53
+ "anthropic-beta": "prompt-caching-2024-07-31"
54
+ },
55
+ max_tokens=2048,
56
+ system=system_message,
57
+ tools=tools,
58
+ messages=messages
59
+ )
60
+
61
+ for content in response.content:
62
+ if content.type == 'tool_use':
63
+ # print(content.input)
64
+ # print(type(content.input))
65
+ print('Found tool_use!')
66
+ return schema.model_validate(content.input)
67
+
68
+ print('ERROR: No tool_use found!')
69
+
70
+
71
+ def follow_structure(json_info, schema):
72
+ print('Following structure via Anthropic...')
73
+ tools = [
74
+ {
75
+ "name": "extract_garment_info",
76
+ "description": FOLLOW_SCHEMA_HUMAN_MESSAGE,
77
+ "input_schema": schema.model_json_schema(),
78
+ "cache_control": {"type": "ephemeral"}
79
+ }
80
+ ]
81
+
82
+ print('DEBUG: human message**************************')
83
+ print(FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info=json_info))
84
+ text_messages = [{
85
+ "type": "text",
86
+ "text": FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info=json_info),
87
+ }]
88
+
89
+ system_message = [
90
+ {
91
+ "type": "text",
92
+ "text": FOLLOW_SCHEMA_SYSTEM_MESSAGE
93
+ }
94
+ ]
95
+
96
+ messages=[
97
+ {
98
+ "role": "user",
99
+ "content": text_messages
100
+ }
101
+ ]
102
+
103
+ response = client.messages.create(
104
+ model="claude-3-5-sonnet-20240620",
105
+ extra_headers={
106
+ "anthropic-beta": "prompt-caching-2024-07-31"
107
+ },
108
+ max_tokens=2048,
109
+ system=system_message,
110
+ tools=tools,
111
+ messages=messages
112
+ )
113
+
114
+ for content in response.content:
115
+ if content.type == 'tool_use':
116
+ # print(content.input)
117
+ # print(type(content.input))
118
+ print('Found tool_use!***********************')
119
+ print(content.input)
120
+ return schema.model_validate(content.input['json_info'])
121
+
122
+ print('ERROR: No tool_use found!')
llm_api/constants.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ EXTRACT_INFO_HUMAN_MESSAGE = \
2
+ "Output properties of the product in the image."
3
+
4
+ EXTRACT_INFO_SYSTEM_MESSAGE = \
5
+ "You are an expert at structured data extraction. You will be given an image of a product and should output the its properties into the given structure."
6
+
7
+ FOLLOW_SCHEMA_HUMAN_MESSAGE = \
8
+ """Convert following attributes to structured schema. Keep all the keys and number of values. Only replace the values themselves. :
9
+
10
+ {json_info}"""
11
+
12
+ FOLLOW_SCHEMA_SYSTEM_MESSAGE = \
13
+ "You are an expert at structured data extraction. You will be given an dictionary of attributes of a product and should output the its properties into the given structure."
14
+
15
+
16
+ if __name__ == '__main__':
17
+ print('Run test cases...')
18
+ print(FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info='{"color": "red"}'))
19
+ print(FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info='{"color": "red", "size": "small"}'))
20
+ print(FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info='{"color": "red", "size": "small", "material": "cotton"}'))
llm_api/exceptions.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ class RefusalError(Exception):
2
+ """Exception raised when the model refuses to respond."""
3
+ def __init__(self, message="The model refused to respond to the given input."):
4
+ self.message = message
5
+ super().__init__(self.message)
llm_api/langchain_api.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .utils import get_data_format, get_image_data
2
+ from langchain_anthropic import ChatAnthropic
3
+ from langchain_openai import ChatOpenAI
4
+ from dotenv import load_dotenv
5
+ from langchain_core.messages import HumanMessage, SystemMessage
6
+ from schema_structured import Garment as StructuredGarment
7
+ from schema_free import Garment as FreeGarment
8
+
9
+
10
+ load_dotenv()
11
+
12
+
13
+ anthropic_llm = ChatAnthropic(
14
+ model="claude-3-5-sonnet-20240620",
15
+ temperature=0,
16
+ max_tokens=1024,
17
+ timeout=None,
18
+ max_retries=2,
19
+ # other params...
20
+ )
21
+
22
+ openai_llm = ChatOpenAI(
23
+ model="gpt-4o",
24
+ temperature=0,
25
+ max_tokens=None,
26
+ timeout=None,
27
+ max_retries=2,
28
+ # api_key="...", # if you prefer to pass api key in directly instaed of using env vars
29
+ # base_url="...",
30
+ # organization="...",
31
+ # other params...
32
+ )
33
+
34
+
35
+ def extract_info(image_paths, provider, schema):
36
+ if provider == 'anthropic':
37
+ llm = anthropic_llm
38
+ elif provider == 'openai':
39
+ llm = openai_llm
40
+ else:
41
+ raise ValueError('Invalid provider')
42
+
43
+ text_message = [{"type": "text", "text": "describe the product in the set of images"}]
44
+ image_message = [
45
+ {
46
+ "type": "image_url",
47
+ "image_url": {"url": f"data:image/{get_data_format(image_path)};base64,{get_image_data(image_path)}"},
48
+ }
49
+ for image_path in image_paths
50
+ ]
51
+ system_text= "You are a helpful assistant that describes the product in the set of images."
52
+ human_message = HumanMessage(content=text_message + image_message)
53
+ structured_llm = llm.with_structured_output(schema)
54
+ if provider == 'anthropic':
55
+ ai_msg = structured_llm.invoke([human_message], system=system_text)
56
+ elif provider == 'openai':
57
+ system_message = SystemMessage(content=system_text)
58
+ ai_msg = structured_llm.invoke([system_message, human_message]) # add system message later
59
+
60
+ return ai_msg
61
+
62
+
63
+ def follow_structure(json_info, provider, schema):
64
+ if provider == 'anthropic':
65
+ llm = anthropic_llm
66
+ elif provider == 'openai':
67
+ llm = openai_llm
68
+ else:
69
+ raise ValueError('Invalid provider')
70
+
71
+ text_message = [{"type": "text", "text": f"Convert following attributes to structured schema. Keep all the keys and number of values. Only replace the values themselves. :\n\n{json_info}"}]
72
+ system_text= "You are an expert at structured data extraction. You will be given an dictionary of attributes of a product and should output the its properties into the given structure."
73
+ human_message = HumanMessage(content=text_message)
74
+ structured_llm = llm.with_structured_output(schema)
75
+ if provider == 'anthropic':
76
+ ai_msg = structured_llm.invoke([human_message], system=system_text)
77
+ elif provider == 'openai':
78
+ system_message = SystemMessage(content=system_text)
79
+ ai_msg = structured_llm.invoke([system_message, human_message]) # add system message later
80
+
81
+ return ai_msg
82
+
83
+
84
+ if __name__ == '__main__':
85
+ print('Running tests...')
86
+ print("Test 1: Provider Anthropic, Schema Structure")
87
+ info = extract_info(['1.png', '2.png'], provider='anthropic', schema=StructuredGarment)
88
+ json_info = info.model_dump_json()
89
+ print(json_info)
90
+ print('Test 2: Provider OpenAI, Schema Structure')
91
+ info = extract_info(['1.png', '2.png'], provider='openai', schema=StructuredGarment)
92
+ json_info = info.model_dump_json()
93
+ print(json_info)
94
+ print('Test 3: Provider Anthropic, Schema Free')
95
+ info = extract_info(['1.png', '2.png'], provider='anthropic', schema=FreeGarment)
96
+ json_info = info.model_dump_json()
97
+ print(json_info)
98
+ print('Test 4: Provider OpenAI, Schema Free')
99
+ info = extract_info(['1.png', '2.png'], provider='openai', schema=FreeGarment)
100
+ json_info = info.model_dump_json()
101
+ print(json_info)
llm_api/native_api.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from dotenv import load_dotenv
3
+ from . import openai_api as openai_info_extractor
4
+ from . import anthropic_api as anthropic_extractor
5
+
6
+ def encode_image(image_path):
7
+ with open(image_path, "rb") as image_file:
8
+ return base64.b64encode(image_file.read()).decode('utf-8')
9
+
10
+
11
+ def extract_info(image_paths, provider, schema):
12
+ if provider == 'anthropic':
13
+ extractor = anthropic_extractor
14
+ elif provider == 'openai':
15
+ extractor = openai_info_extractor
16
+ else:
17
+ raise ValueError('Invalid provider')
18
+
19
+ return extractor.extract_info(image_paths, schema)
20
+
21
+
22
+ def follow_structure(json_info, provider, schema):
23
+ if provider == 'anthropic':
24
+ extractor = anthropic_extractor
25
+ elif provider == 'openai':
26
+ extractor = openai_info_extractor
27
+ else:
28
+ raise ValueError('Invalid provider')
29
+
30
+ return extractor.follow_structure(json_info, schema)
llm_api/openai_api.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from dotenv import load_dotenv
3
+ from .utils import get_data_format, get_image_data
4
+ from openai import OpenAI, BadRequestError
5
+ from .exceptions import RefusalError
6
+ from .constants import EXTRACT_INFO_HUMAN_MESSAGE, EXTRACT_INFO_SYSTEM_MESSAGE,FOLLOW_SCHEMA_HUMAN_MESSAGE, FOLLOW_SCHEMA_SYSTEM_MESSAGE
7
+
8
+ load_dotenv(override=True)
9
+ client = OpenAI()
10
+
11
+
12
+ def extract_info(img_paths, schema):
13
+ print('Extracting info via OpenAI...')
14
+ text_content = [
15
+ {
16
+ "type": "text",
17
+ "text": EXTRACT_INFO_HUMAN_MESSAGE,
18
+ },
19
+ ]
20
+ image_content = [
21
+ {
22
+ "type": "image_url",
23
+ "image_url": {
24
+ "url": f"data:image/{get_image_data(img_path)};base64,{get_image_data(img_path)}",
25
+ },
26
+ }
27
+ for img_path in img_paths
28
+ ]
29
+ response = client.beta.chat.completions.parse(
30
+ model="gpt-4o-2024-08-06",
31
+ messages=[
32
+ {
33
+ "role": "system",
34
+ "content": EXTRACT_INFO_SYSTEM_MESSAGE,
35
+ },
36
+ {
37
+ "role": "user",
38
+ "content": text_content + image_content,
39
+ }
40
+ ],
41
+ max_tokens=1000,
42
+ response_format=schema,
43
+ logprobs=True,
44
+ top_logprobs=2,
45
+ temperature=0.0,
46
+ # top_p=.0000000000000000000001
47
+ )
48
+ if response.choices[0].message.refusal:
49
+ raise RefusalError('OpenAI refused to respond to the request')
50
+
51
+ content = response.choices[0].message.content
52
+ parsed_data = json.loads(content)
53
+ model_data = schema.model_validate(parsed_data)
54
+
55
+ return model_data
56
+
57
+
58
+ def follow_structure(json_info, schema):
59
+ print('Following structure via OpenAI...')
60
+ text_content = [
61
+ {
62
+ "type": "text",
63
+ "text": FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info=json_info),
64
+ },
65
+ ]
66
+ response = client.beta.chat.completions.parse(
67
+ model="gpt-4o-2024-08-06",
68
+ messages=[
69
+ {
70
+ "role": "system",
71
+ "content": FOLLOW_SCHEMA_SYSTEM_MESSAGE,
72
+ },
73
+ {
74
+ "role": "user",
75
+ "content": text_content,
76
+ }
77
+ ],
78
+ max_tokens=1000,
79
+ response_format=schema,
80
+ logprobs=True,
81
+ top_logprobs=2,
82
+ temperature=0.0,
83
+ # top_p=.0000000000000000000001
84
+ )
85
+
86
+ if response.choices[0].message.refusal:
87
+ raise RefusalError('OpenAI refused to respond to the request')
88
+
89
+ content = response.choices[0].message.content
90
+ parsed_data = json.loads(content)
91
+ model_data = schema.model_validate(parsed_data)
92
+
93
+ return model_data
94
+
llm_api/utils.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+
3
+
4
+ def get_image_data(image_path):
5
+ with open(image_path, "rb") as f:
6
+ image_data = base64.b64encode(f.read()).decode("utf-8")
7
+ return image_data
8
+
9
+
10
+ def get_data_format(image_path):
11
+ image_format = image_path.split(".")[-1]
12
+ if image_format == "jpg":
13
+ image_format = "jpeg"
14
+ return image_format
read_schema_free.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from typing import Union
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ # avoid using the 'import' string, including words like 'important', etc.
7
+ class UpperGarmentProperties(BaseModel):
8
+ upper_category: str
9
+ neck: str
10
+ sleeve: str
11
+ shoulder: str
12
+ waist: str
13
+ length: str
14
+
15
+
16
+ class LowerGarmentProperties(BaseModel):
17
+ lower_category: str
18
+ waist: str
19
+ hip: str
20
+ rise: str
21
+ leg: str
22
+
23
+
24
+ class HatProperties(BaseModel):
25
+ style: str
26
+ brim: str
27
+
28
+ class TargetAudience(BaseModel):
29
+ age_range: str
30
+ style_preference: str
31
+ lifestyle: str
32
+
33
+ class Closure(BaseModel):
34
+ color: str
35
+ type: str
36
+ location: str
37
+
38
+ class Pattern(BaseModel):
39
+ type: str
40
+ color: list[str]
41
+
42
+ class Garment(BaseModel): # don't rename this class
43
+ category: str = Field(..., description='Category of the garment')
44
+ gender: str
45
+ material: str
46
+ color: list[str] = Field(..., description='Color of the garment')
47
+ pattern: Pattern
48
+ style: str
49
+ closure: Closure
50
+ fit: str = Field(..., description='Should be one of slim fit, regular fit, loose fit')
51
+ season: list[str]
52
+ occasion: list[str]
53
+ special_occasion: list[str] = Field(..., description='List up to three special occasions, such as weddings, halloween or graduation')
54
+ usage: list[str]
55
+ pairing: list[str]
56
+ target_audience: list[TargetAudience]
57
+ properties: Union[UpperGarmentProperties, LowerGarmentProperties, HatProperties]
read_schema_structured.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from typing import Union
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+
7
+ # avoid using the 'import' string, including words like 'important', etc.
8
+ class NeckType(str, Enum):
9
+ ROUND = "Round neck"
10
+ V_NECK = "V-neck"
11
+ COLLAR = "Collar"
12
+ OFF_SHOULDER = "Off-shoulder"
13
+ HALTER = "Halter"
14
+ OTHER = "Other"
15
+
16
+ class Color(str, Enum):
17
+ SCARLET = "Scarlet" # A bright red color
18
+ AZURE = "Azure" # A bright blue color
19
+ EMERALD = "Emerald" # A bright green color
20
+ AMBER = "Amber" # A yellow-orange color
21
+ EBONY = "Ebony" # A dark black color
22
+ IVORY = "Ivory" # A creamy white color
23
+ FUCHSIA = "Fuchsia" # A bright pink-purple color
24
+ VIOLET = "Violet" # A purple color
25
+ TANGERINE = "Tangerine" # A bright orange color
26
+ CHESTNUT = "Chestnut" # A reddish-brown color
27
+ SLATE = "Slate" # A gray color
28
+ NAVY = "Navy" # A dark blue color
29
+ SILVER = "Silver" # A metallic gray color
30
+ GOLD = "Gold" # A metallic yellow color
31
+ BEIGE = "Beige" # A light brown color
32
+ MULTI = "Multicolor" # Multiple colors
33
+ OTHER = "Other" # Any other color
34
+
35
+ # class Color(str, Enum):
36
+ # RED = "Red"
37
+ # ORANGE = "Orange"
38
+ # YELLOW = "Yellow"
39
+ # GREEN = "Green"
40
+ # BLUE = "Blue"
41
+ # PURPLE = "Purple"
42
+ # PINK = "Pink"
43
+ # BROWN = "Brown"
44
+ # BLACK = "Black"
45
+ # WHITE = "White"
46
+ # GRAY = "Gray"
47
+ # # OTHER = "Other"
48
+
49
+ class Sleeve(str, Enum):
50
+ SHORT = "Short"
51
+ LONG = "Long"
52
+ SLEEVELESS = "Sleeveless"
53
+ OTHER = "Other"
54
+
55
+ class Shoulder(str, Enum):
56
+ REGULAR = "Regular"
57
+ DROP = "Drop"
58
+ PUFF = "Puff"
59
+ COLD_SHOULDER = "Cold shoulder"
60
+ OTHER = "Other"
61
+
62
+ class Waist(str, Enum):
63
+ REGULAR = "Regular"
64
+ HIGH = "High"
65
+ LOW = "Low"
66
+ OTHER = "Other"
67
+
68
+ class UpperLength(str, Enum):
69
+ CROPPED = "Cropped"
70
+ REGULAR = "Regular"
71
+ LONG = "Long"
72
+ OTHER = "Other"
73
+
74
+ class UpperGarmentSubcategory(str, Enum):
75
+ T_SHIRT = "T-shirt"
76
+ BLOUSE = "Blouse"
77
+ SHIRT = "Shirt"
78
+ SWEATER = "Sweater"
79
+ JACKET = "Jacket"
80
+ HOODIE = "Hoodie"
81
+ DRESS = "Dress"
82
+ OTHER = "Other"
83
+
84
+ class LowerGarmentCategory(str, Enum):
85
+ SHORTS = "Shorts"
86
+ PANTS = "Pants"
87
+ SKIRT = "Skirt"
88
+ JEANS = "Jeans"
89
+ OTHER = "Other"
90
+
91
+ class PatternType(str, Enum):
92
+ SOLID = "Solid"
93
+ STRIPED = "Striped"
94
+ CHECKERED = "Checkered"
95
+ FLORAL = "Floral"
96
+ POLKA_DOT = "Polka dot"
97
+ OTHER = "Other"
98
+
99
+ class Pattern(BaseModel):
100
+ type: PatternType
101
+ color: list[Color]
102
+
103
+ class HipSize(str, Enum):
104
+ REGULAR = "Regular"
105
+ WIDE = "Wide"
106
+ SKINNY = "Skinny"
107
+ OTHER = "Other"
108
+
109
+ class Rise(str, Enum):
110
+ REGULAR = "Regular"
111
+ HIGH = "High"
112
+ LOW = "Low"
113
+ OTHER = "Other"
114
+
115
+ class LegWidth(str, Enum):
116
+ REGULAR = "Regular"
117
+ WIDE = "Wide"
118
+ SKINNY = "Skinny"
119
+ OTHER = "Other"
120
+
121
+ class UpperGarmentProperties(BaseModel):
122
+ upper_category: UpperGarmentSubcategory
123
+ neck: NeckType
124
+ sleeve: Sleeve
125
+ shoulder: Shoulder
126
+ waist: Waist
127
+ length: UpperLength
128
+
129
+ class LowerGarmentProperties(BaseModel):
130
+ lower_category: LowerGarmentCategory
131
+ waist: Waist
132
+ hip: HipSize
133
+ rise: Rise
134
+ leg: LegWidth
135
+
136
+ class HatStyle(str, Enum):
137
+ BEANIE = "Beanie"
138
+ BERET = "Beret"
139
+ BUCKET = "Bucket"
140
+ CAP = "Cap"
141
+ FEDORA = "Fedora"
142
+ VISOR = "Visor"
143
+ OTHER = "Other"
144
+
145
+ class Brim(str, Enum):
146
+ NONE = "None"
147
+ SHORT = "Short"
148
+ MEDIUM = "Medium"
149
+ LONG = "Long"
150
+ OTHER = "Other"
151
+
152
+ class HatProperties(BaseModel):
153
+ style: HatStyle
154
+ brim: Brim
155
+
156
+ class Category(str, Enum):
157
+ UPPER_GARMENT = "Upper garment"
158
+ LOWER_GARMENT = "Lower garment"
159
+ HAT = "Hat"
160
+ OTHER = "Other"
161
+
162
+ class Gender(str, Enum):
163
+ MALE = "Male"
164
+ FEMALE = "Female"
165
+ UNISEX = "Unisex"
166
+ OTHER = "Other"
167
+
168
+ class Material(str, Enum):
169
+ COTTON = "Cotton"
170
+ POLYESTER = "Polyester"
171
+ WOOL = "Wool"
172
+ SILK = "Silk"
173
+ LINEN = "Linen"
174
+ LEATHER = "Leather"
175
+ DENIM = "Denim"
176
+ OTHER = "Other"
177
+
178
+ class TargetAudienceAgeRange(str, Enum):
179
+ KIDS = "Kids"
180
+ TEENS = "Teens"
181
+ ADULTS = "Adults"
182
+ SENIORS = "Seniors"
183
+ OTHER = "Other"
184
+
185
+ class TargetAudienceStylePreference(str, Enum):
186
+ TRENDY = "Trendy"
187
+ CLASSIC = "Classic"
188
+ VINTAGE = "Vintage"
189
+ BOHEMIAN = "Bohemian"
190
+ OTHER = "Other"
191
+
192
+ class TargetAudienceLifestyle(str, Enum):
193
+ ACTIVE = "Active"
194
+ CASUAL = "Casual"
195
+ FORMAL = "Formal"
196
+ PARTY = "Party"
197
+ OTHER = "Other"
198
+
199
+ class TargetAudience(BaseModel):
200
+ age_range: TargetAudienceAgeRange
201
+ style_preference: TargetAudienceStylePreference
202
+ lifestyle: TargetAudienceLifestyle
203
+
204
+ class Style(str, Enum):
205
+ CASUAL = "Casual"
206
+ FORMAL = "Formal"
207
+ SPORTS = "Sports"
208
+ PARTY = "Party"
209
+ OTHER = "Other"
210
+
211
+ class ClosureType(str, Enum):
212
+ BUTTON = "Button"
213
+ ZIPPER = "Zipper"
214
+ LACE = "Lace"
215
+ HOOK = "Hook"
216
+ TIE = "Tie"
217
+ VELCRO = "Velcro"
218
+ BUCKLE = "Buckle"
219
+ NONE = "None"
220
+ OTHER = "Other"
221
+
222
+ class ClosureLocation(str, Enum):
223
+ FRONT = "Front"
224
+ BACK = "Back"
225
+ SIDE = "Side"
226
+ NECK = "Neck"
227
+ WAIST = "Waist"
228
+ OTHER = "Other"
229
+
230
+ class Closure(BaseModel):
231
+ color: Color
232
+ type: ClosureType
233
+ location: ClosureLocation
234
+
235
+ class Fit(str, Enum):
236
+ REGULAR = "Regular"
237
+ SLIM = "Slim"
238
+ LOOSE = "Loose"
239
+ OTHER = "Other"
240
+
241
+ class Season(str, Enum):
242
+ ALL_SEASONS = "All seasons"
243
+ SPRING = "Spring"
244
+ SUMMER = "Summer"
245
+ FALL = "Fall"
246
+ WINTER = "Winter"
247
+
248
+ class Occasion(str, Enum):
249
+ CASUAL = "Casual"
250
+ FORMAL = "Formal"
251
+ PARTY = "Party"
252
+ SPORTS = "Sports"
253
+ WORK = "Work"
254
+ OTHER = "Other"
255
+
256
+ class Usage(str, Enum):
257
+ DAILY = "Daily"
258
+ SPECIAL = "Special"
259
+ WORKOUT = "Workout"
260
+ SLEEP = "Sleep"
261
+ PARTY = "Party"
262
+ OTHER = "Other"
263
+
264
+ class Pairing(str, Enum):
265
+ JEANS = "Jeans"
266
+ SHORTS = "Shorts"
267
+ SKIRT = "Skirt"
268
+ LEGGINGS = "Leggings"
269
+ TROUSERS = "Trousers"
270
+ DRESS = "Dress"
271
+ CLUTCH = "Clutch"
272
+ HEELS = "Heels"
273
+ SANDALS = "Sandals"
274
+ JEWELRY = "Jewelry"
275
+ OTHER = "Other"
276
+
277
+ class SpecialOccasion(str, Enum):
278
+ WEDDING = "Wedding"
279
+ PROM = "Prom"
280
+ HALLOWEEN = "Halloween"
281
+ GRADUATION = "Graduation"
282
+ BIRTHDAY = "Birthday"
283
+ BRUNCH = "Brunch"
284
+ OTHER = "Other"
285
+
286
+ class Garment(BaseModel): # don't rename this class
287
+ category: Category
288
+ gender: Gender
289
+ material: Material
290
+ color: list[Color]
291
+ pattern: Pattern
292
+ style: Style
293
+ closure: Closure
294
+ fit: Fit
295
+ season: list[Season]
296
+ occasion: list[Occasion]
297
+ special_occasion: list[SpecialOccasion] = Field(..., description='List up to three special occasions, such as weddings, halloween or graduation')
298
+ usage: list[Usage]
299
+ pairing: list[Pairing]
300
+ target_audience: list[TargetAudience]
301
+ properties: Union[UpperGarmentProperties, LowerGarmentProperties, HatProperties]
schema_free.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from typing import Union
3
+ from pydantic import BaseModel, Field
4
+
5
+ #####
6
+ # avoid using the 'import' string, including words like 'important', etc.
7
+ class UpperGarmentProperties(BaseModel):
8
+ upper_category: str
9
+ neck: str
10
+ sleeve: str
11
+ shoulder: str
12
+ waist: str
13
+ length: str
14
+
15
+
16
+ class LowerGarmentProperties(BaseModel):
17
+ lower_category: str
18
+ waist: str
19
+ hip: str
20
+ rise: str
21
+ leg: str
22
+
23
+
24
+ class HatProperties(BaseModel):
25
+ style: str
26
+ brim: str
27
+
28
+ class TargetAudience(BaseModel):
29
+ age_range: str
30
+ style_preference: str
31
+ lifestyle: str
32
+
33
+ class Closure(BaseModel):
34
+ color: str
35
+ type: str
36
+ location: str
37
+
38
+ class Pattern(BaseModel):
39
+ type: str
40
+ color: list[str]
41
+
42
+ class Garment(BaseModel): # don't rename this class
43
+ category: str = Field(..., description='Category of the garment')
44
+ gender: str
45
+ material: str
46
+ color: list[str] = Field(..., description='Color of the garment')
47
+ pattern: Pattern
48
+ style: str
49
+ closure: Closure
50
+ fit: str = Field(..., description='Should be one of slim fit, regular fit, loose fit')
51
+ season: list[str]
52
+ occasion: list[str]
53
+ special_occasion: list[str] = Field(..., description='List up to three special occasions, such as weddings, halloween or graduation')
54
+ usage: list[str]
55
+ pairing: list[str]
56
+ target_audience: list[TargetAudience]
57
+ properties: Union[UpperGarmentProperties, LowerGarmentProperties, HatProperties]
schema_structured.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from typing import Union
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ #####
7
+ # avoid using the 'import' string, including words like 'important', etc.
8
+ class NeckType(str, Enum):
9
+ ROUND = "Round neck"
10
+ V_NECK = "V-neck"
11
+ COLLAR = "Collar"
12
+ OFF_SHOULDER = "Off-shoulder"
13
+ HALTER = "Halter"
14
+ OTHER = "Other"
15
+
16
+ class Color(str, Enum):
17
+ SCARLET = "Scarlet" # A bright red color
18
+ AZURE = "Azure" # A bright blue color
19
+ EMERALD = "Emerald" # A bright green color
20
+ AMBER = "Amber" # A yellow-orange color
21
+ EBONY = "Ebony" # A dark black color
22
+ IVORY = "Ivory" # A creamy white color
23
+ FUCHSIA = "Fuchsia" # A bright pink-purple color
24
+ VIOLET = "Violet" # A purple color
25
+ TANGERINE = "Tangerine" # A bright orange color
26
+ CHESTNUT = "Chestnut" # A reddish-brown color
27
+ SLATE = "Slate" # A gray color
28
+ NAVY = "Navy" # A dark blue color
29
+ SILVER = "Silver" # A metallic gray color
30
+ GOLD = "Gold" # A metallic yellow color
31
+ BEIGE = "Beige" # A light brown color
32
+ MULTI = "Multicolor" # Multiple colors
33
+ OTHER = "Other" # Any other color
34
+
35
+ # class Color(str, Enum):
36
+ # RED = "Red"
37
+ # ORANGE = "Orange"
38
+ # YELLOW = "Yellow"
39
+ # GREEN = "Green"
40
+ # BLUE = "Blue"
41
+ # PURPLE = "Purple"
42
+ # PINK = "Pink"
43
+ # BROWN = "Brown"
44
+ # BLACK = "Black"
45
+ # WHITE = "White"
46
+ # GRAY = "Gray"
47
+ # # OTHER = "Other"
48
+
49
+ class Sleeve(str, Enum):
50
+ SHORT = "Short"
51
+ LONG = "Long"
52
+ SLEEVELESS = "Sleeveless"
53
+ OTHER = "Other"
54
+
55
+ class Shoulder(str, Enum):
56
+ REGULAR = "Regular"
57
+ DROP = "Drop"
58
+ PUFF = "Puff"
59
+ COLD_SHOULDER = "Cold shoulder"
60
+ OTHER = "Other"
61
+
62
+ class Waist(str, Enum):
63
+ REGULAR = "Regular"
64
+ HIGH = "High"
65
+ LOW = "Low"
66
+ OTHER = "Other"
67
+
68
+ class UpperLength(str, Enum):
69
+ CROPPED = "Cropped"
70
+ REGULAR = "Regular"
71
+ LONG = "Long"
72
+ OTHER = "Other"
73
+
74
+ class UpperGarmentSubcategory(str, Enum):
75
+ T_SHIRT = "T-shirt"
76
+ BLOUSE = "Blouse"
77
+ SHIRT = "Shirt"
78
+ SWEATER = "Sweater"
79
+ JACKET = "Jacket"
80
+ HOODIE = "Hoodie"
81
+ DRESS = "Dress"
82
+ OTHER = "Other"
83
+
84
+ class LowerGarmentCategory(str, Enum):
85
+ SHORTS = "Shorts"
86
+ PANTS = "Pants"
87
+ SKIRT = "Skirt"
88
+ JEANS = "Jeans"
89
+ OTHER = "Other"
90
+
91
+ class PatternType(str, Enum):
92
+ SOLID = "Solid"
93
+ STRIPED = "Striped"
94
+ CHECKERED = "Checkered"
95
+ FLORAL = "Floral"
96
+ POLKA_DOT = "Polka dot"
97
+ OTHER = "Other"
98
+
99
+ class Pattern(BaseModel):
100
+ type: PatternType
101
+ color: list[Color]
102
+
103
+ class HipSize(str, Enum):
104
+ REGULAR = "Regular"
105
+ WIDE = "Wide"
106
+ SKINNY = "Skinny"
107
+ OTHER = "Other"
108
+
109
+ class Rise(str, Enum):
110
+ REGULAR = "Regular"
111
+ HIGH = "High"
112
+ LOW = "Low"
113
+ OTHER = "Other"
114
+
115
+ class LegWidth(str, Enum):
116
+ REGULAR = "Regular"
117
+ WIDE = "Wide"
118
+ SKINNY = "Skinny"
119
+ OTHER = "Other"
120
+
121
+ class UpperGarmentProperties(BaseModel):
122
+ upper_category: UpperGarmentSubcategory
123
+ neck: NeckType
124
+ sleeve: Sleeve
125
+ shoulder: Shoulder
126
+ waist: Waist
127
+ length: UpperLength
128
+
129
+ class LowerGarmentProperties(BaseModel):
130
+ lower_category: LowerGarmentCategory
131
+ waist: Waist
132
+ hip: HipSize
133
+ rise: Rise
134
+ leg: LegWidth
135
+
136
+ class HatStyle(str, Enum):
137
+ BEANIE = "Beanie"
138
+ BERET = "Beret"
139
+ BUCKET = "Bucket"
140
+ CAP = "Cap"
141
+ FEDORA = "Fedora"
142
+ VISOR = "Visor"
143
+ OTHER = "Other"
144
+
145
+ class Brim(str, Enum):
146
+ NONE = "None"
147
+ SHORT = "Short"
148
+ MEDIUM = "Medium"
149
+ LONG = "Long"
150
+ OTHER = "Other"
151
+
152
+ class HatProperties(BaseModel):
153
+ style: HatStyle
154
+ brim: Brim
155
+
156
+ class Category(str, Enum):
157
+ UPPER_GARMENT = "Upper garment"
158
+ LOWER_GARMENT = "Lower garment"
159
+ HAT = "Hat"
160
+ OTHER = "Other"
161
+
162
+ class Gender(str, Enum):
163
+ MALE = "Male"
164
+ FEMALE = "Female"
165
+ UNISEX = "Unisex"
166
+ OTHER = "Other"
167
+
168
+ class Material(str, Enum):
169
+ COTTON = "Cotton"
170
+ POLYESTER = "Polyester"
171
+ WOOL = "Wool"
172
+ SILK = "Silk"
173
+ LINEN = "Linen"
174
+ LEATHER = "Leather"
175
+ DENIM = "Denim"
176
+ OTHER = "Other"
177
+
178
+ class TargetAudienceAgeRange(str, Enum):
179
+ KIDS = "Kids"
180
+ TEENS = "Teens"
181
+ ADULTS = "Adults"
182
+ SENIORS = "Seniors"
183
+ OTHER = "Other"
184
+
185
+ class TargetAudienceStylePreference(str, Enum):
186
+ TRENDY = "Trendy"
187
+ CLASSIC = "Classic"
188
+ VINTAGE = "Vintage"
189
+ BOHEMIAN = "Bohemian"
190
+ OTHER = "Other"
191
+
192
+ class TargetAudienceLifestyle(str, Enum):
193
+ ACTIVE = "Active"
194
+ CASUAL = "Casual"
195
+ FORMAL = "Formal"
196
+ PARTY = "Party"
197
+ OTHER = "Other"
198
+
199
+ class TargetAudience(BaseModel):
200
+ age_range: TargetAudienceAgeRange
201
+ style_preference: TargetAudienceStylePreference
202
+ lifestyle: TargetAudienceLifestyle
203
+
204
+ class Style(str, Enum):
205
+ CASUAL = "Casual"
206
+ FORMAL = "Formal"
207
+ SPORTS = "Sports"
208
+ PARTY = "Party"
209
+ OTHER = "Other"
210
+
211
+ class ClosureType(str, Enum):
212
+ BUTTON = "Button"
213
+ ZIPPER = "Zipper"
214
+ LACE = "Lace"
215
+ HOOK = "Hook"
216
+ TIE = "Tie"
217
+ VELCRO = "Velcro"
218
+ BUCKLE = "Buckle"
219
+ NONE = "None"
220
+ OTHER = "Other"
221
+
222
+ class ClosureLocation(str, Enum):
223
+ FRONT = "Front"
224
+ BACK = "Back"
225
+ SIDE = "Side"
226
+ NECK = "Neck"
227
+ WAIST = "Waist"
228
+ OTHER = "Other"
229
+
230
+ class Closure(BaseModel):
231
+ color: Color
232
+ type: ClosureType
233
+ location: ClosureLocation
234
+
235
+ class Fit(str, Enum):
236
+ REGULAR = "Regular"
237
+ SLIM = "Slim"
238
+ LOOSE = "Loose"
239
+ OTHER = "Other"
240
+
241
+ class Season(str, Enum):
242
+ ALL_SEASONS = "All seasons"
243
+ SPRING = "Spring"
244
+ SUMMER = "Summer"
245
+ FALL = "Fall"
246
+ WINTER = "Winter"
247
+
248
+ class Occasion(str, Enum):
249
+ CASUAL = "Casual"
250
+ FORMAL = "Formal"
251
+ PARTY = "Party"
252
+ SPORTS = "Sports"
253
+ WORK = "Work"
254
+ OTHER = "Other"
255
+
256
+ class Usage(str, Enum):
257
+ DAILY = "Daily"
258
+ SPECIAL = "Special"
259
+ WORKOUT = "Workout"
260
+ SLEEP = "Sleep"
261
+ PARTY = "Party"
262
+ OTHER = "Other"
263
+
264
+ class Pairing(str, Enum):
265
+ JEANS = "Jeans"
266
+ SHORTS = "Shorts"
267
+ SKIRT = "Skirt"
268
+ LEGGINGS = "Leggings"
269
+ TROUSERS = "Trousers"
270
+ DRESS = "Dress"
271
+ CLUTCH = "Clutch"
272
+ HEELS = "Heels"
273
+ SANDALS = "Sandals"
274
+ JEWELRY = "Jewelry"
275
+ OTHER = "Other"
276
+
277
+ class SpecialOccasion(str, Enum):
278
+ WEDDING = "Wedding"
279
+ PROM = "Prom"
280
+ HALLOWEEN = "Halloween"
281
+ GRADUATION = "Graduation"
282
+ BIRTHDAY = "Birthday"
283
+ BRUNCH = "Brunch"
284
+ OTHER = "Other"
285
+
286
+ class Garment(BaseModel): # don't rename this class
287
+ category: Category
288
+ gender: Gender
289
+ material: Material
290
+ color: list[Color]
291
+ pattern: Pattern
292
+ style: Style
293
+ closure: Closure
294
+ fit: Fit
295
+ season: list[Season]
296
+ occasion: list[Occasion]
297
+ special_occasion: list[SpecialOccasion] = Field(..., description='List up to three special occasions, such as weddings, halloween or graduation')
298
+ usage: list[Usage]
299
+ pairing: list[Pairing]
300
+ target_audience: list[TargetAudience]
301
+ properties: Union[UpperGarmentProperties, LowerGarmentProperties, HatProperties]