Karthik71212 commited on
Commit
d061432
Β·
verified Β·
1 Parent(s): 9b2a90e

Update model_api.py

Browse files
Files changed (1) hide show
  1. model_api.py +162 -22
model_api.py CHANGED
@@ -1,22 +1,162 @@
1
- import os
2
- from huggingface_hub import InferenceClient
3
-
4
- def query_model(prompt):
5
- HF_TOKEN = os.getenv("HF_TOKEN")
6
- client = InferenceClient(
7
- model="Qwen/Qwen2.5-72B-Instruct",
8
- token=HF_TOKEN
9
- )
10
- response = client.chat_completion(
11
- messages=[
12
- {
13
- "role": "system",
14
- "content": "You are a certified professional fitness trainer. Provide detailed, structured, day-by-day workout plans."
15
- },
16
- {"role": "user", "content": prompt}
17
- ],
18
- max_tokens=2500,
19
- temperature=0.7
20
- )
21
- return response.choices[0].message.content
22
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, time
2
+
3
+ def query_model(prompt, max_tokens=1500):
4
+ """Single Groq API call."""
5
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY", "").strip()
6
+
7
+ if not GROQ_API_KEY:
8
+ raise ValueError(
9
+ "GROQ_API_KEY is not set.\n\n"
10
+ "Steps to fix:\n"
11
+ "1. Go to https://console.groq.com β†’ sign up free\n"
12
+ "2. Click 'API Keys' β†’ 'Create API Key'\n"
13
+ "3. Copy the key (starts with gsk_...)\n"
14
+ "4. In your HuggingFace Space β†’ Settings β†’ Variables and Secrets\n"
15
+ " β†’ Add secret: Name = GROQ_API_KEY, Value = gsk_xxxxxxxxxxxx\n"
16
+ "5. Restart the Space"
17
+ )
18
+
19
+ try:
20
+ from groq import Groq
21
+ client = Groq(api_key=GROQ_API_KEY)
22
+
23
+ response = client.chat.completions.create(
24
+ model="llama-3.3-70b-versatile", # fastest + best quality on Groq
25
+ messages=[
26
+ {
27
+ "role": "system",
28
+ "content": (
29
+ "You are a certified professional fitness trainer. "
30
+ "Provide detailed, structured, day-by-day workout plans exactly as instructed."
31
+ )
32
+ },
33
+ {"role": "user", "content": prompt}
34
+ ],
35
+ max_tokens=max_tokens,
36
+ temperature=0.7,
37
+ )
38
+ return response.choices[0].message.content
39
+
40
+ except Exception as e:
41
+ err = str(e)
42
+
43
+ if "401" in err or "invalid_api_key" in err.lower() or "authentication" in err.lower():
44
+ raise ValueError(
45
+ "❌ Groq API key is invalid or expired.\n\n"
46
+ "Fix: Go to https://console.groq.com/keys β†’ create a new key β†’ "
47
+ "update GROQ_API_KEY in your HuggingFace Space Secrets."
48
+ ) from None
49
+
50
+ if "429" in err or "rate_limit" in err.lower() or "rate limit" in err.lower():
51
+ raise ValueError(
52
+ "⏳ Groq rate limit hit. Wait 60 seconds and try again.\n\n"
53
+ "Free tier: 6,000 tokens/min. Upgrade at console.groq.com for higher limits."
54
+ ) from None
55
+
56
+ if "503" in err or "504" in err or "timeout" in err.lower():
57
+ raise ValueError(
58
+ "⚑ Groq server busy. Please try again in a few seconds."
59
+ ) from None
60
+
61
+ raise
62
+
63
+
64
+ def query_model_chunked(name, gender, height, weight, goal, fitness_level,
65
+ equipment, days_per_week=5, months=1,
66
+ progress_callback=None):
67
+ """
68
+ Generate a long plan by splitting into chunks of 3 days each.
69
+ Groq is fast enough (~2-3s per chunk) so even 30-day plans finish in ~30s.
70
+ progress_callback(chunk_num, total_chunks, days_done, total_days) β€” optional.
71
+ Returns: (full_plan_text, bmi, bmi_cat)
72
+ """
73
+ from prompt_builder import calculate_bmi, bmi_category, bmi_advice
74
+
75
+ bmi = calculate_bmi(weight, height)
76
+ bmi_cat = bmi_category(bmi)
77
+ advice = bmi_advice(bmi_cat)
78
+
79
+ total_days = min(days_per_week * 4 * months, 30)
80
+ eq_list = ", ".join(equipment) if equipment else "Bodyweight only"
81
+
82
+ intensity_map = {
83
+ "Beginner": "2–3 sets, moderate weight, 90s rest. Prioritise form.",
84
+ "Intermediate": "3–4 sets, progressive overload, 60–75s rest.",
85
+ "Advanced": "4–5 sets, heavy compounds, 45–60s rest, supersets.",
86
+ }
87
+ intensity = intensity_map.get(fitness_level, "3 sets, 60s rest.")
88
+
89
+ CHUNK_SIZE = 3 # 3 days per call β€” well within Groq token limits
90
+ chunks = []
91
+ start_day = 1
92
+ total_chunks = max(1, (total_days + CHUNK_SIZE - 1) // CHUNK_SIZE)
93
+
94
+ while start_day <= total_days:
95
+ end_day = min(start_day + CHUNK_SIZE - 1, total_days)
96
+ chunk_num = len(chunks) + 1
97
+
98
+ if progress_callback:
99
+ progress_callback(chunk_num, total_chunks, start_day - 1, total_days)
100
+
101
+ context_note = ""
102
+ if chunks:
103
+ context_note = (
104
+ f"(Continue from Day {start_day}. Do NOT repeat Days 1–{start_day-1}. "
105
+ f"Vary muscle groups from previous days.)"
106
+ )
107
+
108
+ prompt = f"""Fitness trainer. Generate ONLY Days {start_day}-{end_day} of a {total_days}-day plan.
109
+ Client: {name}, {gender}, {height}cm/{weight}kg, BMI {bmi:.1f} ({bmi_cat}), Goal: {goal}, Level: {fitness_level}, Equipment: {eq_list}.
110
+ {context_note}
111
+
112
+ For EACH day use EXACTLY this format:
113
+ ## Day N - [Muscle Group]
114
+ **Warm-Up** - Exercise: 2x10, Exercise: 2x10
115
+ **Main Workout**
116
+ - ExerciseName β€” 3x12 reps (rest 60s)
117
+ - ExerciseName β€” 3x12 reps (rest 60s)
118
+ - ExerciseName β€” 3x12 reps (rest 60s)
119
+ - ExerciseName β€” 3x12 reps (rest 60s)
120
+ - ExerciseName β€” 3x12 reps (rest 60s)
121
+ **Cool-Down** - Stretch1, Stretch2
122
+
123
+ Rules: vary muscle groups each day, {fitness_level} appropriate, use {eq_list} only, intensity: {intensity}.
124
+ {"End with 1 motivational sentence for "+name+"." if end_day == total_days else "No motivational text β€” more days follow."}
125
+ Output ONLY Days {start_day}-{end_day}. No preamble. No extra text.
126
+ """
127
+
128
+ # Retry up to 3 times on transient errors
129
+ for attempt in range(3):
130
+ try:
131
+ chunk_text = query_model(prompt, max_tokens=1500)
132
+ break
133
+ except ValueError as e:
134
+ # Rate limit β€” wait and retry
135
+ err = str(e)
136
+ if "rate limit" in err.lower() and attempt < 2:
137
+ wait = 65 # wait just over 1 minute for rate limit window to reset
138
+ if progress_callback:
139
+ progress_callback(chunk_num, total_chunks, start_day - 1, total_days,
140
+ status=f"Rate limit β€” waiting {wait}s…")
141
+ time.sleep(wait)
142
+ continue
143
+ raise
144
+ except Exception as e:
145
+ err = str(e)
146
+ if attempt < 2:
147
+ time.sleep(5 * (attempt + 1))
148
+ continue
149
+ raise
150
+
151
+ chunks.append(chunk_text.strip())
152
+ start_day = end_day + 1
153
+
154
+ # Small pause between chunks to respect rate limits on free tier
155
+ if start_day <= total_days:
156
+ time.sleep(1)
157
+
158
+ if progress_callback:
159
+ progress_callback(total_chunks, total_chunks, total_days, total_days)
160
+
161
+ full_plan = "\n\n".join(chunks)
162
+ return full_plan, bmi, bmi_cat