hank1229 commited on
Commit
10d8299
·
verified ·
1 Parent(s): 53b3e9a

Upload 3 files

Browse files
Files changed (3) hide show
  1. models/llm.py +126 -0
  2. models/test_llm.py +162 -0
  3. models/vision.py +50 -0
models/llm.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from transformers import pipeline
3
+
4
+ class StyleSavvy:
5
+ def __init__(
6
+ self,
7
+ model_name: str = "google/flan-t5-large",
8
+ device: int = -1, # -1 = CPU, or GPU index
9
+ max_length: int = 150,
10
+ ):
11
+ # A local instruction-tuned T5 model
12
+ self.pipe = pipeline(
13
+ "text2text-generation",
14
+ model=model_name,
15
+ tokenizer=model_name,
16
+ device=device,
17
+ )
18
+ self.max_length = max_length
19
+ # TODO: Modification: Add more prompts to the advise function
20
+ # to make it more specific to the user's needs.
21
+ # The function now takes in the user's body type, face shape, and occasion
22
+ # and generates style tips accordingly.
23
+
24
+ def advise(self, items, body_type, face_shape, occasion):
25
+ prompt = (
26
+ f"The user is {body_type}-shaped with a {face_shape} face, "
27
+ f"attending a {occasion}. They are wearing: "
28
+ + ", ".join(i["label"] for i in items)
29
+ + ".\n\nPlease list 5 concise style tips as bullet points:"
30
+ )
31
+
32
+ # Generate with supported args only
33
+ result = self.pipe(
34
+ prompt,
35
+ max_length=self.max_length,
36
+ num_beams=4,
37
+ early_stopping=True,
38
+ do_sample=False
39
+ )[0]["generated_text"].strip()
40
+
41
+ return result
42
+
43
+
44
+
45
+
46
+ # import torch
47
+
48
+ # # models/llm.py
49
+
50
+ # # models/llm.py
51
+
52
+ # import os
53
+ # from typing import List
54
+ # from transformers import pipeline, Pipeline
55
+
56
+ # # Force CPU modes (avoid any MPS/CUDA issues on macOS)
57
+ # os.environ["CUDA_VISIBLE_DEVICES"] = ""
58
+ # os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "0"
59
+
60
+ # class StyleSavvy:
61
+ # def __init__(
62
+ # self,
63
+ # model_name: str = "openlm-research/open_llama_3b_v2",
64
+ # device: int = -1, # -1 = CPU
65
+ # max_new_tokens: int = 100,
66
+ # temperature: float = 0.7,
67
+ # top_p: float = 0.9,
68
+ # ):
69
+ # """
70
+ # Uses OpenLLaMA-3B-v2 (≈3B params) for fast, local inference.
71
+ # """
72
+ # # Setup a causal text-generation pipeline
73
+ # self.pipe: Pipeline = pipeline(
74
+ # "text-generation",
75
+ # model=model_name,
76
+ # tokenizer=model_name,
77
+ # device=device,
78
+ # )
79
+ # # GPT‐style models need a pad token to avoid warnings
80
+ # if self.pipe.tokenizer.pad_token_id is None:
81
+ # self.pipe.tokenizer.pad_token = self.pipe.tokenizer.eos_token
82
+
83
+ # self.max_new_tokens = max_new_tokens
84
+ # self.temperature = temperature
85
+ # self.top_p = top_p
86
+
87
+ # def advise(
88
+ # self,
89
+ # items: List[str],
90
+ # body_type: str,
91
+ # face_shape: str,
92
+ # occasion: str
93
+ # ) -> List[str]:
94
+ # """
95
+ # Builds a strict instruction prompt and returns exactly five "- " bullets.
96
+ # """
97
+ # labels = ", ".join(items) if items else "an outfit"
98
+ # prompt = (
99
+ # "You are a professional fashion consultant.\n"
100
+ # f"The user is {body_type}-shaped with a {face_shape} face, attending {occasion}.\n"
101
+ # f"They are wearing: {labels}.\n\n"
102
+ # "Please provide exactly five concise style tips, each on its own line, "
103
+ # "and starting with \"- \". No extra text."
104
+ # )
105
+
106
+ # # Generate
107
+ # output = self.pipe(
108
+ # prompt,
109
+ # max_new_tokens=self.max_new_tokens,
110
+ # do_sample=True,
111
+ # temperature=self.temperature,
112
+ # top_p=self.top_p,
113
+ # return_full_text=False,
114
+ # )[0]["generated_text"]
115
+
116
+ # # Extract bullets
117
+ # tips = [ln.strip() for ln in output.splitlines() if ln.strip().startswith("- ")]
118
+ # # Fallback: split on sentences if fewer than 5 bullets
119
+ # if len(tips) < 5:
120
+ # candidates = [s.strip() for s in output.replace("\n"," ").split(".") if s.strip()]
121
+ # tips = [f"- {candidates[i]}" for i in range(min(5, len(candidates)))]
122
+
123
+ # return tips[:5]
124
+
125
+
126
+
models/test_llm.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # # test_llm.py
2
+ # """
3
+ # Test harness for StyleSavvy LLM prompts.
4
+ # Defines multiple prompt templates and evaluates the generated outputs,
5
+ # checking for the expected number of bullet-point style tips.
6
+ # """
7
+ # from models.llm import StyleSavvy
8
+
9
+ # # Variant prompt templates with placeholders
10
+ # PROMPT_TEMPLATES = {
11
+ # "occasion_driven": (
12
+ # "You are an expert fashion stylist. A client is preparing for {occasion}. "
13
+ # "They have a {body_type}-shaped body and a {face_shape} face. They’re currently wearing: {items}. "
14
+ # "Give 3 to 5 *distinct* style tips focused on making them look their best at the event. "
15
+ # "Make the suggestions relevant to the setting, weather, and formality of the occasion. "
16
+ # "Avoid repeating any advice."
17
+ # ),
18
+
19
+ # "function_based": (
20
+ # "You're advising someone with a {body_type} build and {face_shape} face. "
21
+ # "They're attending a {occasion} and are wearing {items}. "
22
+ # "Suggest 3–5 concise fashion improvements or enhancements. "
23
+ # "Each suggestion should be unique and tailored to the event. "
24
+ # "Include practical choices for color, layering, accessories, or footwear. "
25
+ # "Avoid repeating words or phrases."
26
+ # ),
27
+
28
+ # "intent_style": (
29
+ # "Act as a high-end personal stylist. Your client has a {body_type} body shape and a {face_shape} face. "
30
+ # "They're going to a {occasion} and are wearing {items}. "
31
+ # "Write 3 to 5 brief but powerful styling suggestions to elevate their look. "
32
+ # "Focus on intent—what feeling or impression each style choice creates for the event."
33
+ # ),
34
+ # }
35
+
36
+
37
+ # # Test parameters
38
+ # BODY_TYPE = "Slim"
39
+ # FACE_SHAPE = "Round"
40
+ # OCCASION = "Rooftop Evening Party"
41
+ # ITEMS = ["shirt", "jeans", "jacket","shoes"]
42
+
43
+ # if __name__ == "__main__":
44
+ # advisor = StyleSavvy()
45
+
46
+ # for name, template in PROMPT_TEMPLATES.items():
47
+ # # Build prompt by replacing placeholders
48
+ # prompt = template.format(
49
+ # body_type=BODY_TYPE,
50
+ # face_shape=FACE_SHAPE,
51
+ # occasion=OCCASION,
52
+ # items=", ".join(ITEMS)
53
+ # )
54
+ # print(f"=== Testing template: {name} ===")
55
+ # print("Prompt:")
56
+ # print(prompt)
57
+
58
+ # # Generate output (use only supported args)
59
+ # result = advisor.pipe(
60
+ # prompt,
61
+ # max_length=advisor.max_length,
62
+ # early_stopping=True,
63
+ # do_sample=False
64
+ # )[0]["generated_text"].strip()
65
+
66
+ # print("Generated output:")
67
+ # print(result)
68
+
69
+ # # Extract bullet lines
70
+ # bullets = [ln for ln in result.splitlines() if ln.strip().startswith("- ")]
71
+ # print(f"Number of bullets detected: {len(bullets)}")
72
+ # for i, b in enumerate(bullets, start=1):
73
+ # print(f" {i}. {b}")
74
+ # print("" + "-"*40)
75
+
76
+
77
+ # test_llm.py
78
+ """
79
+ Test harness for StyleSavvy LLM prompts.
80
+ Evaluates multiple prompt templates and parses the generated outputs into distinct tips.
81
+ """
82
+
83
+ from models.llm import StyleSavvy
84
+
85
+ # Variant prompt templates with placeholders
86
+ PROMPT_TEMPLATES = {
87
+ "direct_instruction": (
88
+ "You are a professional fashion stylist. A client with a {body_type} body shape "
89
+ "and {face_shape} face is preparing for a {occasion}. They are currently wearing {items}. "
90
+ "Give exactly five different styling tips to improve their outfit. "
91
+ "Each tip should be concise, actionable, and relevant to the event. Start each tip on a new line."
92
+ ),
93
+ "category_expansion": (
94
+ "As a high-end fashion advisor, provide five styling tips for a {body_type}-shaped person "
95
+ "with a {face_shape} face attending a {occasion}. They are currently wearing {items}. "
96
+ "Offer one tip for each of the following categories: silhouette, color, accessories, footwear, and layering. "
97
+ "Each tip must be brief, specific, and clearly separated by a line break."
98
+ ),
99
+ "event_aesthetic": (
100
+ "Imagine you're curating a perfect outfit for a {body_type}-shaped individual with a {face_shape} face "
101
+ "attending {occasion}. They are wearing {items}. Suggest 5 ways to enhance their style, focusing on event-appropriate aesthetics. "
102
+ "Write each tip as a separate sentence on a new line. Do not repeat advice or themes."
103
+ ),
104
+ "fashion_editor": (
105
+ "As a fashion editor writing for a style magazine, outline five unique styling tips for a {body_type}-shaped reader "
106
+ "with a {face_shape} face who is attending {occasion}. They currently wear {items}. "
107
+ "Each recommendation should reflect expertise, relevance to the occasion, and a unique style element. "
108
+ "Deliver all five tips in a list format, starting each on a new line."
109
+ ),
110
+ "influencer_style": (
111
+ "You’re an influencer known for your sharp styling advice. One of your followers has a {body_type} body and "
112
+ "{face_shape} face, and they're attending {occasion}. They’ve sent you a photo wearing {items}. "
113
+ "Reply with exactly five snappy, modern style tips they can use to upgrade their outfit for the event. "
114
+ "Make sure each tip is short, non-repetitive, and on its own line."
115
+ ),
116
+ }
117
+
118
+
119
+ # Test parameters
120
+ BODY_TYPE = "Slim"
121
+ FACE_SHAPE = "Round"
122
+ OCCASION = "Rooftop Evening Party"
123
+ ITEMS = ["jeans", "jacket", "shoes"]
124
+
125
+ if __name__ == "__main__":
126
+ advisor = StyleSavvy()
127
+
128
+ for name, template in PROMPT_TEMPLATES.items():
129
+ print(f"=== Testing template: {name} ===")
130
+
131
+ # Build prompt
132
+ prompt = template.format(
133
+ body_type=BODY_TYPE,
134
+ face_shape=FACE_SHAPE,
135
+ occasion=OCCASION,
136
+ items=", ".join(ITEMS)
137
+ )
138
+ print("Prompt:\n" + prompt)
139
+
140
+ # Generate response
141
+ result = advisor.pipe(
142
+ prompt,
143
+ max_length=advisor.max_length,
144
+ early_stopping=True,
145
+ num_beams=4,
146
+ no_repeat_ngram_size=3,
147
+ do_sample=False)[0]["generated_text"].strip()
148
+
149
+ print("\nRaw generated output:\n" + result)
150
+
151
+ # Parse into tips (bullets or sentence)
152
+ lines = result.splitlines()
153
+ tips = [ln.strip("-*0123456789. ").strip() for ln in lines if ln.strip()]
154
+ if len(tips) < 3:
155
+ # fallback to sentence split
156
+ tips = [p.strip() for p in result.split(".") if p.strip()]
157
+ tips = list(dict.fromkeys(tips)) # remove duplicates
158
+
159
+ print(f"\n💡 Parsed {len(tips)} style tips:")
160
+ for i, tip in enumerate(tips[:5], 1):
161
+ print(f"{i}. {tip}")
162
+ print("-" * 40)
models/vision.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # models/vision.py -- Working
3
+
4
+ from transformers import pipeline
5
+ from PIL import Image
6
+
7
+ class VisionModel:
8
+ def __init__(
9
+ self,
10
+ model_name: str = "valentinafeve/yolos-fashionpedia",
11
+ threshold: float = 0.7
12
+ ):
13
+ self.pipe = pipeline("object-detection", model=model_name)
14
+ self.threshold = threshold
15
+
16
+ def detect(self, image: Image.Image):
17
+ # 1) Ensure RGB
18
+ if image.mode != "RGB":
19
+ image = image.convert("RGB")
20
+
21
+ # 2) Run detection
22
+ results = self.pipe(image)
23
+
24
+ # 3) Process & filter
25
+ processed = []
26
+ for r in results:
27
+ score = float(r["score"])
28
+ if score < self.threshold:
29
+ continue
30
+
31
+ # r["box"] is a dict: {"xmin":..., "ymin":..., "xmax":..., "ymax":...}
32
+ box = r["box"]
33
+ coords = [
34
+ float(box["xmin"]),
35
+ float(box["ymin"]),
36
+ float(box["xmax"]),
37
+ float(box["ymax"]),
38
+ ]
39
+
40
+ processed.append({
41
+ "label": r["label"],
42
+ "score": score,
43
+ "box": coords
44
+ })
45
+
46
+ return processed
47
+
48
+
49
+
50
+