thanhnt-cf commited on
Commit
28f26e5
·
1 Parent(s): 44e85d0

update to support user schema

Browse files
.gitignore CHANGED
@@ -48,11 +48,19 @@ Thumbs.db
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
 
 
 
 
 
 
 
48
  *.mov
49
  *.wmv
50
 
51
+ .env
52
+
53
  env/
54
  __pycache__/
55
+ testset/
56
  *.ipynb
57
  server.crt
58
  server.key
59
  server.csr
60
+ sample_data.json
61
+
62
+ test_result
63
+
64
+ read_schema_free.py
65
+ read_schema_structured.py
66
+ dev.py
app.py CHANGED
@@ -5,46 +5,54 @@ 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
- # from utils import log_input, log_output
9
 
10
  load_dotenv('.env', override=True)
 
 
11
 
12
- def extract_free_fn(gallery, provider, schema):
 
 
13
  # write schema to file before calling extract_free_properties
14
  try:
15
- img_paths = [item[0] for item in gallery]
16
- # request_id = log_input('extract', img_paths, provider, schema)
17
  if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
18
  with open('schema_free.py', 'r') as f:
19
  default_schema = f.read()
20
  import_part = default_schema.split('#####')[0]
21
  print('Executing freestyle schema...')
22
  full_schema = import_part + schema
 
 
 
 
 
 
 
 
23
  with open('read_schema_free.py', 'w') as f:
24
  f.write(full_schema)
25
- exec(import_part + schema, globals())
26
  print('Executed freestyle schema')
27
  else:
28
  print('SCHEMA ELSE')
29
  raise Exception('Invalid schema')
30
  except Exception as e:
31
- return f"ERROR: {e}", {}, []
 
32
 
33
  try:
34
- free_attributes = extract_info(img_paths, provider, Garment)
35
  free_attributes = free_attributes.model_dump_json()
36
  except RefusalError as e:
37
- return f"ERROR: {e}", {}, []
38
  except BadRequestError as e:
39
- return f"ERROR: {e}", {}, []
40
- except Exception as e:
41
- return f"ERROR: {e}", {}, []
42
- # log_output(request_id, str(free_attributes))
43
- return f'OK - provider: {provider}', free_attributes, [1] * 100
44
 
45
  def follow_schema_fn(free_attributes, provider, probs, schema):
46
  try:
47
- # request_id = log_input('follow', None, provider, schema)
48
  if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
49
  with open('schema_structured.py', 'r') as f:
50
  default_schema = f.read()
@@ -58,21 +66,19 @@ def follow_schema_fn(free_attributes, provider, probs, schema):
58
  else:
59
  print('SCHEMA ELSE')
60
  raise Exception('Invalid schema')
61
- except Exception as e:
62
- return f"ERROR: {e}", {}
63
 
64
  try:
65
- schema_attributes = follow_structure(free_attributes, provider, Garment)
66
  schema_attributes = schema_attributes.model_dump_json()
67
  except RefusalError as e:
68
- return f"ERROR: {e}", {}
69
  except BadRequestError as e:
70
- return f"ERROR: {e}", {}
71
- except Exception as e:
72
- return f"ERROR: {e}", {}
73
 
74
- # log_output(request_id, str(schema_attributes))
75
- return f'OK - provider: {provider}', schema_attributes
76
 
77
  with gr.Blocks(title='Internal Demo for Attribution') as demo:
78
  with gr.Row():
@@ -83,6 +89,7 @@ with gr.Blocks(title='Internal Demo for Attribution') as demo:
83
  # gr.Markdown('''<div style="text-align: left; font-size: 18px;">Upload images of a garment and click Extract Freestyle</div>''')
84
  gallery = gr.Gallery(label='Images', type='filepath')
85
  probs_text = gr.Textbox(label='Probabilities', placeholder='Probabilities', visible=False)
 
86
  provider = gr.Dropdown(label='Provider', choices=['openai', 'anthropic'], value='openai')
87
  button_extract = gr.Button(value='Extract Freestyle')
88
  with gr.Column(scale=4):
@@ -105,8 +112,8 @@ with gr.Blocks(title='Internal Demo for Attribution') as demo:
105
  free_schema = gr.TextArea(label='Freestyle Schema', placeholder='Freestyle Schema', visible=True, value=schema_free_text, interactive=True)
106
  structured_schema = gr.TextArea(label='Structured Schema', placeholder='Schema', visible=True, value=schema_structured_text, interactive=True)
107
 
108
- button_extract.click(extract_free_fn, [gallery, provider, free_schema], [status_free_text, free_attributes, probs_text])
109
- button_follow.click(follow_schema_fn, [free_attributes, provider, probs_text, structured_schema], [status_structured_text, schema_attributes])
110
 
111
  # demo.launch(server_name="0.0.0.0", server_port=7688, share=False, ssl_verify=True, ssl_certfile=None, ssl_keyfile=None, auth=None)
112
  # 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)
 
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
 
10
  load_dotenv('.env', override=True)
11
+ garment_categories = ['Auto', 'Upper Garment', 'Lower Garment', 'Hat', 'Luggage', 'Handbag', 'Makeup', 'Chair', 'Carpet', 'Watch', 'Cookware', 'Tableware', 'Sleepware', 'BathroomItem']
12
+ schema_categories = ['Auto', 'UpperGarmentProperties', 'LowerGarmentProperties', 'HatProperties', 'LuggageProperties', 'HandbagProperties', 'MakeupProperties', 'ChairProperties', 'CarpetProperties', 'WatchProperties', 'CookwareProperties', 'TablewareProperties', 'SleepwareProperties', 'BathroomItemProperties']
13
 
14
+ def extract_free_fn(gallery, category, provider, schema):
15
+ img_paths = [item[0] for item in gallery]
16
+ category_schema = schema_categories[garment_categories.index(category)]
17
  # write schema to file before calling extract_free_properties
18
  try:
 
 
19
  if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
20
  with open('schema_free.py', 'r') as f:
21
  default_schema = f.read()
22
  import_part = default_schema.split('#####')[0]
23
  print('Executing freestyle schema...')
24
  full_schema = import_part + schema
25
+
26
+ # dynamically change the last line of the schema to include the category schema
27
+ if category_schema in schema_categories[1:]:
28
+ print('Dynamic schema activated')
29
+ schema_lines = full_schema.split('\n')
30
+ schema_lines[-1] = f' properties: {category_schema}'
31
+ full_schema = '\n'.join(schema_lines)
32
+
33
  with open('read_schema_free.py', 'w') as f:
34
  f.write(full_schema)
35
+ exec(full_schema, globals())
36
  print('Executed freestyle schema')
37
  else:
38
  print('SCHEMA ELSE')
39
  raise Exception('Invalid schema')
40
  except Exception as e:
41
+ print(e)
42
+ return 'Invalid schema! Please check the schema or Reload this page to restore default settings', {}, []
43
 
44
  try:
45
+ status_code, free_attributes = extract_info(img_paths, provider, Garment)
46
  free_attributes = free_attributes.model_dump_json()
47
  except RefusalError as e:
48
+ return e.message, {}, []
49
  except BadRequestError as e:
50
+ return e.message, {}, []
51
+
52
+ return f'status: {status_code} - provider: {provider}', free_attributes, [1] * 100
 
 
53
 
54
  def follow_schema_fn(free_attributes, provider, probs, schema):
55
  try:
 
56
  if schema is not None and isinstance(schema, str) and 'import' not in schema.replace("'import'", '').replace("'important'", ''):
57
  with open('schema_structured.py', 'r') as f:
58
  default_schema = f.read()
 
66
  else:
67
  print('SCHEMA ELSE')
68
  raise Exception('Invalid schema')
69
+ except:
70
+ return 'Invalid schema! Please check the schema or Reload this page to restore default settings', {}
71
 
72
  try:
73
+ status_code, schema_attributes = follow_structure(free_attributes, provider, Garment)
74
  schema_attributes = schema_attributes.model_dump_json()
75
  except RefusalError as e:
76
+ return e.message, {}
77
  except BadRequestError as e:
78
+ return e.message, {}
 
 
79
 
80
+ return f'status {status_code} - provider: {provider}', schema_attributes
81
+
82
 
83
  with gr.Blocks(title='Internal Demo for Attribution') as demo:
84
  with gr.Row():
 
89
  # gr.Markdown('''<div style="text-align: left; font-size: 18px;">Upload images of a garment and click Extract Freestyle</div>''')
90
  gallery = gr.Gallery(label='Images', type='filepath')
91
  probs_text = gr.Textbox(label='Probabilities', placeholder='Probabilities', visible=False)
92
+ category = gr.Dropdown(label='Category', choices=garment_categories, value=garment_categories[0])
93
  provider = gr.Dropdown(label='Provider', choices=['openai', 'anthropic'], value='openai')
94
  button_extract = gr.Button(value='Extract Freestyle')
95
  with gr.Column(scale=4):
 
112
  free_schema = gr.TextArea(label='Freestyle Schema', placeholder='Freestyle Schema', visible=True, value=schema_free_text, interactive=True)
113
  structured_schema = gr.TextArea(label='Structured Schema', placeholder='Schema', visible=True, value=schema_structured_text, interactive=True)
114
 
115
+ button_extract.click(extract_free_fn, [gallery, category,provider, free_schema], [status_free_text, free_attributes, probs_text])
116
+ button_follow.click(follow_schema_fn, [free_attributes, category, provider, probs_text, structured_schema], [status_structured_text, schema_attributes])
117
 
118
  # demo.launch(server_name="0.0.0.0", server_port=7688, share=False, ssl_verify=True, ssl_certfile=None, ssl_keyfile=None, auth=None)
119
  # 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)
llm_api/anthropic_api.py CHANGED
@@ -2,6 +2,7 @@ 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()
@@ -47,23 +48,26 @@ def extract_info(img_paths, schema):
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
 
@@ -99,17 +103,19 @@ def follow_structure(json_info, schema):
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':
@@ -117,6 +123,6 @@ def follow_structure(json_info, schema):
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!')
 
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
+ from anthropic import APIStatusError
6
 
7
  load_dotenv(override=True)
8
  client = Anthropic()
 
48
  }
49
  ]
50
 
51
+ try:
52
+ response = client.messages.create(
53
+ model="claude-3-5-sonnet-20240620",
54
+ extra_headers={
55
+ "anthropic-beta": "prompt-caching-2024-07-31"
56
+ },
57
+ max_tokens=2048,
58
+ system=system_message,
59
+ tools=tools,
60
+ messages=messages
61
+ )
62
+ except APIStatusError as e:
63
+ return e.status_code, None
64
 
65
  for content in response.content:
66
  if content.type == 'tool_use':
67
  # print(content.input)
68
  # print(type(content.input))
69
  print('Found tool_use!')
70
+ return 200, schema.model_validate(content.input)
71
 
72
  print('ERROR: No tool_use found!')
73
 
 
103
  "content": text_messages
104
  }
105
  ]
106
+ try:
107
+ response = client.messages.create(
108
+ model="claude-3-5-sonnet-20240620",
109
+ extra_headers={
110
+ "anthropic-beta": "prompt-caching-2024-07-31"
111
+ },
112
+ max_tokens=2048,
113
+ system=system_message,
114
+ tools=tools,
115
+ messages=messages
116
+ )
117
+ except APIStatusError as e:
118
+ return e.status_code, None
119
 
120
  for content in response.content:
121
  if content.type == 'tool_use':
 
123
  # print(type(content.input))
124
  print('Found tool_use!***********************')
125
  print(content.input)
126
+ return 200, schema.model_validate(content.input['json_info'])
127
 
128
  print('ERROR: No tool_use found!')
llm_api/anthropic_vertex_api.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from anthropic import AnthropicVertex as 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
+ }
17
+ ]
18
+
19
+ image_messages = [
20
+ {
21
+ "type": "image",
22
+ "source": {
23
+ "type": "base64",
24
+ "media_type": f"image/{get_data_format(img_path)}",
25
+ "data": get_image_data(img_path)
26
+ }
27
+ } for img_path in img_paths
28
+ ]
29
+
30
+ system_message = [
31
+ {
32
+ "type": "text",
33
+ "text": EXTRACT_INFO_SYSTEM_MESSAGE
34
+ }
35
+ ]
36
+
37
+ text_messages = [{
38
+ "type": "text",
39
+ "text": EXTRACT_INFO_HUMAN_MESSAGE,
40
+ }]
41
+
42
+ messages=[
43
+ {
44
+ "role": "user",
45
+ "content": text_messages + image_messages
46
+ }
47
+ ]
48
+
49
+ response = client.messages.create(
50
+ model="claude-3-5-sonnet@20240620",
51
+ max_tokens=2048,
52
+ system=system_message,
53
+ tools=tools,
54
+ messages=messages
55
+ )
56
+
57
+ for content in response.content:
58
+ if content.type == 'tool_use':
59
+ # print(content.input)
60
+ # print(type(content.input))
61
+ print('Found tool_use!')
62
+ return schema.model_validate(content.input)
63
+
64
+ print('ERROR: No tool_use found!')
65
+
66
+
67
+ def follow_structure(json_info, schema):
68
+ print('Following structure via Anthropic...')
69
+ tools = [
70
+ {
71
+ "name": "extract_garment_info",
72
+ "description": FOLLOW_SCHEMA_HUMAN_MESSAGE,
73
+ "input_schema": schema.model_json_schema()
74
+ }
75
+ ]
76
+
77
+ print('DEBUG: human message**************************')
78
+ print(FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info=json_info))
79
+ text_messages = [{
80
+ "type": "text",
81
+ "text": FOLLOW_SCHEMA_HUMAN_MESSAGE.format(json_info=json_info),
82
+ }]
83
+
84
+ system_message = [
85
+ {
86
+ "type": "text",
87
+ "text": FOLLOW_SCHEMA_SYSTEM_MESSAGE
88
+ }
89
+ ]
90
+
91
+ messages=[
92
+ {
93
+ "role": "user",
94
+ "content": text_messages
95
+ }
96
+ ]
97
+
98
+ response = client.messages.create(
99
+ model="claude-3-5-sonnet@20240620",
100
+ max_tokens=2048,
101
+ system=system_message,
102
+ tools=tools,
103
+ messages=messages
104
+ )
105
+
106
+ for content in response.content:
107
+ if content.type == 'tool_use':
108
+ # print(content.input)
109
+ # print(type(content.input))
110
+ print('Found tool_use!***********************')
111
+ print(content.input)
112
+ return schema.model_validate(content.input['json_info'])
113
+
114
+ print('ERROR: No tool_use found!')
llm_api/langchain_api.py CHANGED
@@ -11,7 +11,7 @@ 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,
 
11
 
12
 
13
  anthropic_llm = ChatAnthropic(
14
+ model="claude-3-5-sonnet-20241022",
15
  temperature=0,
16
  max_tokens=1024,
17
  timeout=None,
llm_api/native_api.py CHANGED
@@ -1,4 +1,5 @@
1
  import base64
 
2
  from . import openai_api as openai_info_extractor
3
  from . import anthropic_api as anthropic_extractor
4
 
 
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
 
llm_api/openai_api.py CHANGED
@@ -52,7 +52,7 @@ def extract_info(img_paths, schema):
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):
@@ -90,5 +90,5 @@ def follow_structure(json_info, schema):
90
  parsed_data = json.loads(content)
91
  model_data = schema.model_validate(parsed_data)
92
 
93
- return model_data
94
 
 
52
  parsed_data = json.loads(content)
53
  model_data = schema.model_validate(parsed_data)
54
 
55
+ return 200, model_data
56
 
57
 
58
  def follow_structure(json_info, schema):
 
90
  parsed_data = json.loads(content)
91
  model_data = schema.model_validate(parsed_data)
92
 
93
+ return 200, model_data
94
 
read_schema_free.py DELETED
@@ -1,57 +0,0 @@
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 DELETED
@@ -1,301 +0,0 @@
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]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,4 +1,6 @@
1
  openai
2
  anthropic
3
  pydantic
4
- python-dotenv
 
 
 
1
  openai
2
  anthropic
3
  pydantic
4
+ python-dotenv
5
+ google-cloud-aiplatform
6
+ anthropic[vertex]
schema_free.py CHANGED
@@ -39,6 +39,147 @@ 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
@@ -53,5 +194,9 @@ class Garment(BaseModel): # don't rename this class
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]
 
39
  type: str
40
  color: list[str]
41
 
42
+ class LuggageProperties(BaseModel):
43
+ luggage_type: str = Field(..., description="Type of luggage, e.g., suitcase, duffel, backpack, etc.")
44
+ size: str = Field(..., description="Size of the luggage, e.g., carry-on, large, extra-large")
45
+ material: str = Field(..., description="Material used, e.g., leather, polyester, polycarbonate")
46
+ color: list[str] = Field(..., description="Color of the luggage")
47
+ weight: str = Field(..., description="Weight of the luggage in kg or lbs")
48
+ compartments: int = Field(..., description="Number of compartments")
49
+ wheels: str = Field(..., description="Wheel type, e.g., 2-wheel, 4-wheel, or spinner")
50
+ handle_type: str = Field(..., description="Type of handle, e.g., retractable, fixed, or no handle")
51
+ closure: Closure = Field(..., description="Closure details like type, color, and location")
52
+ lock_type: str = Field(..., description="Lock type, e.g., TSA, combination, or none")
53
+ expandable: bool = Field(..., description="Whether the luggage is expandable")
54
+ waterproof: bool = Field(..., description="Whether the luggage is waterproof or water-resistant")
55
+
56
+ class HandbagProperties(BaseModel):
57
+ handbag_type: str = Field(..., description="Type of handbag, e.g., tote, crossbody, clutch, etc.")
58
+ size: str = Field(..., description="Size of the handbag, e.g., small, medium, large")
59
+ material: str = Field(..., description="Material used, e.g., leather, canvas, suede")
60
+ color: list[str] = Field(..., description="Color of the handbag")
61
+ weight: str = Field(..., description="Weight of the handbag in kg or lbs")
62
+ compartments: int = Field(..., description="Number of compartments in the handbag")
63
+ strap_type: str = Field(..., description="Type of strap, e.g., adjustable, removable, fixed")
64
+ handle_type: str = Field(..., description="Type of handle, e.g., top handle, shoulder strap, none")
65
+ closure: Closure = Field(..., description="Closure details like type, color, and location")
66
+ lock_type: str = Field(..., description="Lock type, e.g., magnetic, zipper, clasp, or none")
67
+ pattern: Pattern = Field(..., description="Pattern details")
68
+ occasion: list[str] = Field(..., description="Occasions suitable for the handbag, e.g., formal, casual, evening")
69
+ waterproof: bool = Field(..., description="Whether the handbag is waterproof or water-resistant")
70
+
71
+ class MakeupProperties(BaseModel):
72
+ makeup_type: str = Field(..., description="Type of makeup, e.g., foundation, lipstick, eyeshadow, mascara, etc.")
73
+ shade: str = Field(..., description="Shade of the makeup product")
74
+ finish: str = Field(..., description="Finish of the product, e.g., matte, dewy, satin, glossy, etc.")
75
+ texture: str = Field(..., description="Texture of the product, e.g., creamy, powder, liquid")
76
+ skin_type_compatibility: list[str] = Field(..., description="Skin types compatible with the product, e.g., dry, oily, combination")
77
+ waterproof: bool = Field(..., description="Whether the product is waterproof or not")
78
+ long_wear: bool = Field(..., description="Whether the product is long-wearing")
79
+ cruelty_free: bool = Field(..., description="Whether the product is cruelty-free")
80
+ vegan: bool = Field(..., description="Whether the product is vegan")
81
+ ingredients: list[str] = Field(..., description="Key ingredients in the product")
82
+ packaging_type: str = Field(..., description="Type of packaging, e.g., compact, tube, pump bottle")
83
+ application_method: str = Field(..., description="How the product is applied, e.g., brush, sponge, fingers, applicator")
84
+ ingredients: list[str] = Field(..., description="If visible in images, what ingredients are in the product")
85
+
86
+ class ChairProperties(BaseModel):
87
+ chair_type: str = Field(..., description="Type of chair, e.g., office chair, dining chair, lounge chair")
88
+ material: str = Field(..., description="Material used, e.g., wood, metal, fabric")
89
+ upholstery_material: str = Field(..., description="Upholstery material, e.g., leather, fabric, mesh, none")
90
+ color: list[str] = Field(..., description="Color of the chair")
91
+ weight_capacity: str = Field(..., description="Maximum weight capacity of the chair in kg or lbs")
92
+ dimensions: str = Field(..., description="Dimensions of the chair, e.g., height, width, depth")
93
+ adjustable: bool = Field(..., description="Whether the chair is adjustable")
94
+ swivel: bool = Field(..., description="Whether the chair can swivel")
95
+ wheels: bool = Field(..., description="Whether the chair has wheels")
96
+ ergonomic: bool = Field(..., description="Whether the chair is ergonomically designed")
97
+
98
+ class CarpetProperties(BaseModel):
99
+ carpet_type: str = Field(..., description="Type of carpet, e.g., area rug, runner, mat")
100
+ material: str = Field(..., description="Material used, e.g., wool, synthetic, cotton")
101
+ color: list[str] = Field(..., description="Color of the carpet")
102
+ dimensions: str = Field(..., description="Dimensions of the carpet, e.g., length and width")
103
+ pile_height: str = Field(..., description="Pile height of the carpet in mm or inches")
104
+ pattern: Pattern = Field(..., description="Pattern details of the carpet")
105
+ anti_slip: bool = Field(..., description="Whether the carpet has anti-slip backing")
106
+ washable: bool = Field(..., description="Whether the carpet is washable")
107
+ indoor_outdoor: str = Field(..., description="Whether the carpet is meant for indoor or outdoor use")
108
+
109
+ class WatchProperties(BaseModel):
110
+ watch_type: str = Field(..., description="Type of watch, e.g., analog, digital, smart watch, hybrid")
111
+ movement_type: str = Field(..., description="Type of movement, e.g., quartz, mechanical, automatic, digital")
112
+ material: str = Field(..., description="Material of the watch case, e.g., stainless steel, titanium, plastic")
113
+ strap_material: str = Field(..., description="Material of the strap, e.g., leather, rubber, metal, nylon")
114
+ strap_color: list[str] = Field(..., description="Color of the watch strap")
115
+ dial_color: str = Field(..., description="Color of the watch dial")
116
+ water_resistant: bool = Field(..., description="Whether the watch is water-resistant")
117
+ water_resistance_depth: str = Field(..., description="Depth rating for water resistance in meters or feet")
118
+ features: list[str] = Field(..., description="Special features like GPS, heart rate monitor, chronograph, etc.")
119
+ case_diameter: str = Field(..., description="Diameter of the watch case in mm or inches")
120
+ case_thickness: str = Field(..., description="Thickness of the watch case in mm or inches")
121
+ weight: str = Field(..., description="Weight of the watch")
122
+ display_type: str = Field(..., description="Display type for smart/digital watches, e.g., LED, AMOLED, LCD")
123
+ battery_life: str = Field(..., description="Battery life for digital or smart watches")
124
+ clasp_type: str = Field(..., description="Type of clasp or buckle, e.g., deployant, tang buckle, folding clasp")
125
+
126
+ class SleepwareProperties(BaseModel):
127
+ sleepware_type: str = Field(..., description="Type of sleepware, e.g., pillow, duvet, mattress, mattress topper, blanket")
128
+ material: str = Field(..., description="Material used, e.g., cotton, down, memory foam, microfiber")
129
+ filling_material: str = Field(..., description="Filling material for pillows or duvets, e.g., down, feather, polyester")
130
+ firmness: str = Field(..., description="Firmness level for pillows or mattresses, e.g., soft, medium, firm")
131
+ size: str = Field(..., description="Size of the sleepware, e.g., queen, king, standard")
132
+ weight: str = Field(..., description="Weight of the sleepware (mainly for duvets and blankets)")
133
+ temperature_regulation: bool = Field(..., description="Whether the item has temperature regulation properties")
134
+ hypoallergenic: bool = Field(..., description="Whether the item is hypoallergenic")
135
+ machine_washable: bool = Field(..., description="Whether the item is machine washable")
136
+ thread_count: str = Field(..., description="Thread count for items like sheets or pillowcases")
137
+ moisture_wicking: bool = Field(..., description="Whether the material wicks away moisture")
138
+
139
+ class TablewareProperties(BaseModel):
140
+ tableware_type: str = Field(..., description="Type of tableware, e.g., dinner plate, salad bowl, mug, cup, saucer")
141
+ material: str = Field(..., description="Material of the tableware, e.g., porcelain, ceramic, glass, stoneware")
142
+ color: list[str] = Field(..., description="Color of the tableware")
143
+ pattern: Pattern = Field(..., description="Pattern details if applicable")
144
+ diameter: str = Field(..., description="Diameter of the tableware (for plates or bowls)")
145
+ volume: str = Field(..., description="Volume capacity for bowls, cups, mugs in ml or oz")
146
+ dishwasher_safe: bool = Field(..., description="Whether the tableware is dishwasher safe")
147
+ microwave_safe: bool = Field(..., description="Whether the tableware is microwave safe")
148
+ oven_safe: bool = Field(..., description="Whether the tableware is oven safe")
149
+ stackable: bool = Field(..., description="Whether the tableware is stackable")
150
+ chip_resistant: bool = Field(..., description="Whether the tableware is chip-resistant")
151
+
152
+ class CookwareProperties(BaseModel):
153
+ cookware_type: str = Field(..., description="Type of cookware, e.g., skillet, saucepan, stockpot, frying pan")
154
+ material: str = Field(..., description="Material of the cookware, e.g., stainless steel, cast iron, non-stick, aluminum")
155
+ diameter: str = Field(..., description="Diameter of the cookware in cm or inches")
156
+ depth: str = Field(..., description="Depth of the cookware in cm or inches")
157
+ weight: str = Field(..., description="Weight of the cookware in kg or lbs")
158
+ non_stick: bool = Field(..., description="Whether the cookware is non-stick")
159
+ induction_safe: bool = Field(..., description="Whether the cookware is safe for induction stoves")
160
+ oven_safe: bool = Field(..., description="Whether the cookware is oven safe")
161
+ max_oven_temperature: str = Field(..., description="Maximum temperature in Celsius or Fahrenheit for oven use")
162
+ dishwasher_safe: bool = Field(..., description="Whether the cookware is dishwasher safe")
163
+ handle_material: str = Field(..., description="Material of the handle, e.g., stainless steel, silicone, wood")
164
+ lid_included: bool = Field(..., description="Whether the cookware comes with a lid")
165
+ heat_distribution: str = Field(..., description="Heat distribution technology, e.g., tri-ply, aluminum core")
166
+
167
+ class BathroomItemProperties(BaseModel):
168
+ item_type: str = Field(..., description="Type of bathroom item, e.g., towel, bath mat, shower curtain")
169
+ material: str = Field(..., description="Material of the item, e.g., cotton, microfiber, bamboo")
170
+ size: str = Field(..., description="Size of the item, e.g., bath towel, hand towel, washcloth")
171
+ gsm: str = Field(..., description="Grams per square meter (GSM) which indicates the density of the towel fabric")
172
+ color: list[str] = Field(..., description="Color of the bathroom item")
173
+ absorbency: str = Field(..., description="Absorbency level, e.g., high, medium, low")
174
+ quick_dry: bool = Field(..., description="Whether the towel has quick-dry properties")
175
+ softness: str = Field(..., description="Softness rating, e.g., ultra-soft, soft, firm")
176
+ machine_washable: bool = Field(..., description="Whether the item is machine washable")
177
+ pattern: Pattern = Field(..., description="Pattern details if applicable")
178
+ anti_bacterial: bool = Field(..., description="Whether the towel has anti-bacterial properties")
179
+ hypoallergenic: bool = Field(..., description="Whether the towel is hypoallergenic")
180
+
181
+
182
+
183
  class Garment(BaseModel): # don't rename this class
184
  category: str = Field(..., description='Category of the garment')
185
  gender: str
 
194
  special_occasion: list[str] = Field(..., description='List up to three special occasions, such as weddings, halloween or graduation')
195
  usage: list[str]
196
  pairing: list[str]
197
+ microtrends: list[str]
198
+ silhouette: list[str]
199
+ aesthetic: list[str]
200
+ dressing_style: list[str]
201
  target_audience: list[TargetAudience]
202
+ properties: Union[UpperGarmentProperties, LowerGarmentProperties, HatProperties, LuggageProperties, HandbagProperties, MakeupProperties, ChairProperties, CarpetProperties, WatchProperties, CookwareProperties, TablewareProperties, SleepwareProperties, BathroomItemProperties ] = Field(..., description="Specific properties for different product categories")